Initial check in of YAPF 0.1.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b8038e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+#==============================================================================#
+# This file specifies intentionally untracked files that git should ignore.
+# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
+#
+# This file is intentionally different from the output of `git svn show-ignore`,
+# as most of those are useless.
+#==============================================================================#
+
+#==============================================================================#
+# File extensions to be ignored anywhere in the tree.
+#==============================================================================#
+# Temp files created by most text editors.
+*~
+# Merge files created by git.
+*.orig
+# Byte compiled python modules.
+*.pyc
+# vim swap files
+.*.sw?
+.sw?
+#OS X specific files.
+.DS_store
+
+#==============================================================================#
+# Directories to ignore (do not add trailing '/'s, they skip symlinks).
+#==============================================================================#
+# The build directory.
+build
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b5e878e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+# This is the official list of YAPF authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+Google Inc.
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..1ba8539
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,24 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the Software Grant and Corporate Contributor License Agreement.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..bf60fc6
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,13 @@
+# People who have agreed to one of the CLAs and can contribute patches.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# https://developers.google.com/open-source/cla/individual
+# https://developers.google.com/open-source/cla/corporate
+#
+# Names should be added to this file as:
+#     Name <email address>
+
+Bill Wendling <[email protected]>
+Eli Bendersky <[email protected]>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..29a72ec
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,151 @@
+====
+YAPF
+====
+
+Introduction
+============
+
+Most of the current formatters for Python -- e.g., autopep8, and pep8ify -- are
+made to remove lint errors from code. This has some obvious limitations. For
+instance, code that conforms to the PEP 8 guidelines may not be reformatted.
+But it doesn't mean that the code looks good.
+
+YAPF takes a different approach. It's based off of 'clang-format', developed by
+Daniel Jasper. In essence, the algorithm takes the code and reformats it to the
+best formatting that conforms to the style guide, even if the original code
+didn't violate the style guide.
+
+The ultimate goal is that the code YAPF produces is as good as the code that a
+programmer would write if they were following the style guide.
+
+.. contents::
+
+Installation
+============
+
+From source directory::
+
+    $ sudo python ./setup.py install
+
+
+Usage
+=====
+
+<verbatim>
+usage: __main__.py [-h] [-d | -i] [-l START-END | -r] ...
+
+Formatter for Python code.
+
+positional arguments:
+  files
+
+optional arguments:
+  -h, --help            show this help message and exit
+  -d, --diff            print the diff for the fixed source
+  -i, --in-place        make changes to files in place
+  -l START-END, --lines START-END
+                        range of lines to reformat, one-based
+  -r, --recursive       run recursively over directories
+</verbatim>
+
+
+Why Not Improve Existing Tools?
+===============================
+
+We wanted to use clang-format's reformatting algorithm. It's very powerful and
+designed to come up with the best formatting possible. Existing tools were
+created with different goals in mind, and would require extensive modifications
+to convert to using clang-format's algorithm.
+
+
+Can I Use YAPF In My Program?
+=============================
+
+Please do! YAPF was designed to be used as a library as well as a command line
+tool. This means that a tool or IDE plugin is free to use YAPF.
+
+
+Gory Details
+============
+
+Algorithm Design
+----------------
+
+The main data structure in YAPF is the UnwrappedLine object. It holds a list of
+FormatTokens, that we would want to place on a single line if there were no
+column limit. An exception being a comment in the middle of an expression
+statement will force the line to be formatted on more than one line. The
+formatter works on one UnwrappedLine object at a time.
+
+An UnwrappedLine typically won't affect the formatting of lines before or after
+it. There is a part of the algorithm that may join two or more UnwrappedLines
+into one line. For instance, an if-then statement with a short body can be
+placed on a single line:
+
+    if a == 42: continue
+
+YAPF's formatting algorithm creates a weighted tree that acts as the solution
+space for the algorithm. Each node in the tree represents the result of a
+formatting decision --- i.e., whether to split or not to split before a token.
+Each formatting decision has a cost associated with it. Therefore, the cost is
+realized on the edge between two nodes. (In reality, the weighted tree doesn't
+have separate edge objects, so the cost resides on the nodes themselves.)
+
+For example, take the following Python code snippet. For the sake of this
+example, assume that line (1) violates the column limit restriction and needs to
+be reformatted.
+
+
+    1: def xxxxxxxxxxx(aaaaaaaaaaaa, bbbbbbbbb, cccccccc, dddddddd, eeeeee):
+    2:   pass
+
+For line (1), the algorithm will build a tree where each node (a
+FormattingDecisionState object) is the state of the line at that token given the
+decision to split before the token or not. Note: the FormatDecisionState objects
+are copied by value so each node in the graph is unique and a change in one
+doesn't affect other nodes.
+
+Here is a hypothetical subtree of the first five tokens. The value in
+parentheses is the hypothetical cost of splitting before the token. (The left
+hand branch is a decision to split and the right hand branch is a decision not
+to split.)
+
+                               'def'
+                                 |
+                                 |  (0)
+                                 |
+                           'xxxxxxxxxxx'
+                                 |
+                                 |  (0)
+                                 |
+                                '('
+                                 |
+              (3)  +---------------------------+  (1)
+                   |                           |
+                   |                           |
+            'aaaaaaaaaaaa'               'aaaaaaaaaaaa'
+                   |                           |
+                   |                           |
+           +--------------+             +-------------+
+           |              |             |             |
+     (50)  |         (0)  |       (50)  |        (0)  |
+          ','            ','           ','           ','
+
+And so on. Heuristics are used to determine the costs of splitting or not
+splitting. Because a node holds the state of the tree up to a token's insertion,
+it can easily determine if a splitting decision will violate one of the style
+requirements. For instance, the heuristic is able to apply an extra penalty to
+the edge when not splitting between the previous token and the one being added.
+
+There are some instances where we will never want to split the line, because
+doing so will always be detrimental (i.e., it will require a backslash-newline,
+which is very rarely desirable). For line (1), we will never want to split the
+first three tokens: 'def', 'xxxxxxxxxxx', and '('. Nor will we want to split
+between the ')' and the ':' at the end. These regions are said to be
+"unbreakable." This is reflected in the tree by there not being a 'split'
+decision (left hand branch) within the unbreakable region.
+
+Now that we have the tree, we determine what the "best" formatting is by finding
+the path through the tree with the lowest cost.
+
+And that's it!
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..0533b11
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from distutils.core import setup, Command
+
+import yapf
+import yapftests
+
+
+class RunTests(Command):
+  user_options = []
+
+  def initialize_options(self):
+    pass
+
+  def finalize_options(self):
+    pass
+
+  def run(self):
+    tests = unittest.TestSuite(yapftests.suite())
+    runner = unittest.TextTestRunner()
+    runner.run(tests)
+
+
+with open('README', 'r') as fd:
+  setup(
+      name='yapf',
+      version=yapf.__version__,
+      description='A formatter for Python code.',
+      long_description=fd.read(),
+      license='Apache License, Version 2.0',
+      author='Google Inc.',
+      maintainer='Bill Wendling',
+      maintainer_email='[email protected]',
+      packages=['yapf', 'yapf.yapflib'],
+      classifiers=[
+          'Development Status :: 3 - Alpha',
+          'Environment :: Console',
+          'Intended Audience :: Developers',
+          'License :: OSI Approved :: Apache Software License',
+          'Operating System :: OS Independent',
+          'Programming Language :: Python',
+          'Programming Language :: Python :: 2',
+          'Programming Language :: Python :: 2.7',
+          'Programming Language :: Python :: 3',
+          'Programming Language :: Python :: 3.2',
+          'Programming Language :: Python :: 3.3',
+          'Programming Language :: Python :: 3.4',
+          'Topic :: Software Development :: Libraries :: Python Modules',
+          'Topic :: Software Development :: Quality Assurance',
+      ],
+      cmdclass={
+          'test': RunTests,
+      },
+  )
diff --git a/yapf/__init__.py b/yapf/__init__.py
new file mode 100644
index 0000000..e8b97d7
--- /dev/null
+++ b/yapf/__init__.py
@@ -0,0 +1,142 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Yet Another Python Formatter.
+
+YAPF uses the algorithm in clang-format to figure out the "best" formatting for
+Python code. It looks at the program as a series of "unwrappable lines" ---
+i.e., lines which, if there were no column limit, we would place all tokens on
+that line. It then uses a priority queue to figure out what the best formatting
+is --- i.e., the formatting with the least penalty.
+
+It differs from tools like autopep8 and pep8ify in that it doesn't just look for
+violations of the style guide, but looks at the module as a whole, making
+formatting decisions based on what's the best format for each line.
+
+If no filenames are specified, YAPF reads the code from stdin.
+"""
+
+import argparse
+import logging
+import sys
+
+from yapf.yapflib import file_resources
+from yapf.yapflib import yapf_api
+
+__version__ = '0.1'
+
+
+def main(argv):
+  """Main program.
+
+  Arguments:
+    argv: (Positional arguments) A list of files to reformat.
+
+  Returns:
+    0 if there were no errors, non-zero otherwise.
+  """
+  parser = argparse.ArgumentParser(description='Formatter for Python code.')
+  diff_inplace_group = parser.add_mutually_exclusive_group()
+  diff_inplace_group.add_argument(
+      '-d', '--diff', action='store_true',
+      help='print the diff for the fixed source')
+  diff_inplace_group.add_argument(
+      '-i', '--in-place', action='store_true',
+      help='make changes to files in place')
+
+  lines_recursive_group = parser.add_mutually_exclusive_group()
+  lines_recursive_group.add_argument(
+      '-l', '--lines', metavar='START-END', action='append', default=None,
+      help='range of lines to reformat, one-based')
+  lines_recursive_group.add_argument(
+      '-r', '--recursive', action='store_true',
+      help='run recursively over directories')
+
+  parser.add_argument('files', nargs=argparse.REMAINDER)
+  args = parser.parse_args()
+
+  if args.lines and len(args.files) > 1:
+    parser.error('cannot use -l/--lines with more than one file')
+
+  lines = _GetLines(args.lines) if args.lines is not None else None
+  files = file_resources.GetCommandLineFiles(argv[1:], args.recursive)
+  if not files:
+    # No arguments specified. Read code from stdin.
+    if args.in_place or args.diff:
+      parser.error('cannot use --in_place or --diff flags when reading '
+                   'from stdin')
+
+    original_source = []
+    while True:
+      try:
+        # Use 'raw_input' instead of 'sys.stdin.read', because otherwise the
+        # user will need to hit 'Ctrl-D' more than once if they're inputting
+        # the program by hand. 'raw_input' throws an EOFError exception if
+        # 'Ctrl-D' is pressed, which makes it easy to bail out of this loop.
+        original_source.append(raw_input())
+      except EOFError:
+        break
+    sys.stdout.write(yapf_api.FormatCode(
+        unicode('\n'.join(original_source) + '\n'),
+        filename='<stdin>',
+        lines=lines))
+    return 0
+
+  FormatFiles(files, lines, args.in_place)
+  return 0
+
+
+def FormatFiles(filenames, lines, in_place=False):
+  """Format a list of files.
+
+  Arguments:
+    filenames: (list of unicode) A list of files to reformat.
+    lines: (list of tuples of integers) A list of tuples of lines, [start, end],
+      that we want to format. The lines are 1-based indexed. This argument
+      overrides the 'args.lines'. It can be used by third-party code (e.g.,
+      IDEs) when reformatting a snippet of code.
+    in_place: (bool) Modify the files in place.
+  """
+  for filename in filenames:
+    logging.info('Reformatting %s', filename)
+    reformatted_code = yapf_api.FormatFile(filename, lines)
+    if reformatted_code is not None:
+      file_resources.WriteReformattedCode(filename, reformatted_code, in_place)
+
+
+def _GetLines(line_strings):
+  """Parses the start and end lines from a line string like 'start-end'.
+
+  Arguments:
+    line_strings: (array of string) A list of strings representing a line
+      range like 'start-end'.
+
+  Returns:
+    A list of tuples of the start and end line numbers.
+
+  Raises:
+    ValueError: If the line string failed to parse or was an invalid line range.
+  """
+  lines = []
+  for line_string in line_strings:
+    line = map(int, line_string.split('-', 1))
+    if line[0] < 1:
+      raise ValueError('invalid start of line range: %r' % line)
+    if line[0] > line[1]:
+      raise ValueError('end comes before start in line range: %r', line)
+    lines.append(tuple(line))
+  return lines
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/yapf/__main__.py b/yapf/__main__.py
new file mode 100644
index 0000000..b3c65fc
--- /dev/null
+++ b/yapf/__main__.py
@@ -0,0 +1,18 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import sys
+
+import yapf
+
+sys.exit(yapf.main(sys.argv))
diff --git a/yapf/yapflib/__init__.py b/yapf/yapflib/__init__.py
new file mode 100644
index 0000000..e7522b2
--- /dev/null
+++ b/yapf/yapflib/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/yapf/yapflib/blank_line_calculator.py b/yapf/yapflib/blank_line_calculator.py
new file mode 100644
index 0000000..955e000
--- /dev/null
+++ b/yapf/yapflib/blank_line_calculator.py
@@ -0,0 +1,162 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Calculate the number of blank lines between top-level entities.
+
+Calculates how many blank lines we need between classes, functions, and other
+entities at the same level.
+
+  CalculateBlankLines(): the main function exported by this module.
+
+Annotations:
+  newlines: The number of newlines required before the node.
+"""
+
+from lib2to3 import pytree
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+
+_NO_BLANK_LINES = 1
+_ONE_BLANK_LINE = 2
+_TWO_BLANK_LINES = 3
+
+_PYTHON_STATEMENTS = frozenset({
+    'simple_stmt', 'small_stmt', 'expr_stmt', 'print_stmt', 'del_stmt',
+    'pass_stmt', 'break_stmt', 'continue_stmt', 'return_stmt', 'raise_stmt',
+    'yield_stmt', 'import_stmt', 'global_stmt', 'exec_stmt', 'assert_stmt',
+    'if_stmt', 'while_stmt', 'for_stmt', 'try_stmt'
+})
+
+
+def CalculateBlankLines(tree):
+  """Run the blank line calculator visitor over the tree.
+
+  This modifies the tree in place.
+
+  Arguments:
+    tree: the top-level pytree node to annotate with subtypes.
+  """
+  blank_line_calculator = _BlankLineCalculator()
+  blank_line_calculator.Visit(tree)
+
+
+class _BlankLineCalculator(pytree_visitor.PyTreeVisitor):
+  """_BlankLineCalculator - see file-level docstring for a description."""
+
+  def __init__(self):
+    self.class_level = 0
+    self.function_level = 0
+    self.last_comment_lineno = 0
+    self.last_was_decorator = False
+    self.last_was_class_or_function = False
+
+  def Visit_simple_stmt(self, node):  # pylint: disable=invalid-name
+    self.DefaultNodeVisit(node)
+    if pytree_utils.NodeName(node.children[0]) == 'COMMENT':
+      self.last_comment_lineno = node.children[0].lineno
+
+  def Visit_decorator(self, node):  # pylint: disable=invalid-name
+    if (self.last_comment_lineno and
+        self.last_comment_lineno == node.children[0].lineno - 1):
+      self._SetNumNewlines(node.children[0], _NO_BLANK_LINES)
+    else:
+      self._SetNumNewlines(node.children[0], self._GetNumNewlines())
+    for child in node.children:
+      self.Visit(child)
+    self.last_was_decorator = True
+
+  def Visit_classdef(self, node):  # pylint: disable=invalid-name
+    index = self._SetBlankLinesBetweenCommentAndClassFunc(node)
+    self.last_was_decorator = False
+    self.class_level += 1
+    for child in node.children[index:]:
+      self.Visit(child)
+    self.class_level -= 1
+    self.last_was_class_or_function = True
+
+  def Visit_funcdef(self, node):  # pylint: disable=invalid-name
+    index = self._SetBlankLinesBetweenCommentAndClassFunc(node)
+    self.last_was_decorator = False
+    self.function_level += 1
+    for child in node.children[index:]:
+      self.Visit(child)
+    self.function_level -= 1
+    self.last_was_class_or_function = True
+
+  def DefaultNodeVisit(self, node):
+    """Override the default visitor for Node.
+
+    This will set the blank lines required if the last entity was a class or
+    function.
+
+    Arguments:
+      node: (pytree.Node) The node to visit.
+    """
+
+    def GetFirstChildLeaf(node):
+      if isinstance(node, pytree.Leaf):
+        return node
+      return GetFirstChildLeaf(node.children[0])
+
+    if self.last_was_class_or_function:
+      if pytree_utils.NodeName(node) in _PYTHON_STATEMENTS:
+        leaf = GetFirstChildLeaf(node)
+        if pytree_utils.NodeName(leaf) != 'COMMENT':
+          self._SetNumNewlines(leaf, self._GetNumNewlines())
+    self.last_was_class_or_function = False
+    super(_BlankLineCalculator, self).DefaultNodeVisit(node)
+
+  def _SetBlankLinesBetweenCommentAndClassFunc(self, node):
+    """Set the number of blanks between a comment and class or func definition.
+
+    Class and function definitions have leading comments as children of the
+    classdef and functdef nodes.
+
+    Arguments:
+      node: (pytree.Node) The classdef or funcdef node.
+
+    Returns:
+      The index of the first child past the comment nodes.
+    """
+    index = 0
+    while pytree_utils.IsCommentStatement(node.children[index]):
+      # Standalone comments are wrapped in a simple_stmt node with the comment
+      # node as its only child.
+      self.Visit(node.children[index].children[0])
+      self._SetNumNewlines(node.children[index].children[0], _ONE_BLANK_LINE)
+      index += 1
+    if (index and node.children[index].lineno - 1 ==
+        node.children[index - 1].children[0].lineno):
+      self._SetNumNewlines(node.children[index], _NO_BLANK_LINES)
+    else:
+      if self.last_comment_lineno + 1 == node.children[index].lineno:
+        num_newlines = _NO_BLANK_LINES
+      else:
+        num_newlines = self._GetNumNewlines()
+      self._SetNumNewlines(node.children[index], num_newlines)
+    return index
+
+  def _GetNumNewlines(self):
+    if self.last_was_decorator:
+      return _NO_BLANK_LINES
+    elif self._IsTopLevel():
+      return _TWO_BLANK_LINES
+    return _ONE_BLANK_LINE
+
+  def _SetNumNewlines(self, node, num_newlines):
+    pytree_utils.SetNodeAnnotation(node, pytree_utils.Annotation.NEWLINES,
+                                   num_newlines)
+
+  def _IsTopLevel(self):
+    return not (self.class_level or self.function_level)
diff --git a/yapf/yapflib/comment_splicer.py b/yapf/yapflib/comment_splicer.py
new file mode 100644
index 0000000..c0f8864
--- /dev/null
+++ b/yapf/yapflib/comment_splicer.py
@@ -0,0 +1,293 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Comment splicer for lib2to3 trees.
+
+The lib2to3 syntax tree produced by the parser holds comments and whitespace in
+prefix attributes of nodes, rather than nodes themselves. This module provides
+functionality to splice comments out of prefixes and into nodes of their own,
+making them easier to process.
+
+  SpliceComments(): the main function exported by this module.
+"""
+
+from lib2to3 import pygram
+from lib2to3 import pytree
+from lib2to3.pgen2 import token
+
+from yapf.yapflib import pytree_utils
+
+
+def SpliceComments(tree):
+  """Given a pytree, splice comments into nodes of their own right.
+
+  Extract comments from the prefixes where they are housed after parsing.
+  The prefixes that previously housed the comments become empty.
+
+  Args:
+    tree: a pytree.Node - the tree to work on. The tree is modified by this
+        function.
+  """
+  # The previous leaf node encountered in the traversal.
+  # This is a list because Python 2.x doesn't have 'nonlocal' :)
+  prev_leaf = [None]
+  _AnnotateIndents(tree)
+
+  def _VisitNodeRec(node):
+    # This loop may insert into node.children, so we'll iterate over a copy.
+    for child in node.children[:]:
+      if isinstance(child, pytree.Node):
+        # Nodes don't have prefixes.
+        _VisitNodeRec(child)
+      else:
+        if child.prefix.lstrip().startswith('#'):
+          # We have a comment prefix in this child, so splicing is needed.
+          comment_prefix = child.prefix
+          comment_lineno = child.lineno - comment_prefix.count('\n')
+
+          # Remember the leading indentation of this prefix and clear it.
+          # Mopping up the prefix is important because we may go over this same
+          # child in the next iteration...
+          child_prefix = child.prefix.lstrip('\n')
+          prefix_indent = child_prefix[:child_prefix.find('#')]
+          child.prefix = ''
+
+          if child.type == token.NEWLINE:
+            # If the prefix was on a NEWLINE leaf, it's part of the line so it
+            # will be inserted after the previously encountered leaf.
+            # We can't just insert it before the NEWLINE node, because as a
+            # result of the way pytrees are organized, this node can be under
+            # an inappropriate parent.
+            assert prev_leaf[0] is not None
+            pytree_utils.InsertNodesAfter(_CreateCommentsFromPrefix(
+                comment_prefix, comment_lineno,
+                standalone=False), prev_leaf[0])
+          elif child.type == token.DEDENT:
+            # Comment prefixes on DEDENT nodes also deserve special treatment,
+            # because their final placement depends on their prefix.
+            # We'll look for an ancestor of this child with a matching
+            # indentation, and insert the comment after it.
+            ancestor_at_indent = _FindAncestorAtIndent(child, prefix_indent)
+            if ancestor_at_indent.type == token.DEDENT:
+              # Special case where the comment is inserted in the same
+              # indentation level as the DEDENT it was originally attached to.
+              pytree_utils.InsertNodesBefore(_CreateCommentsFromPrefix(
+                  comment_prefix, comment_lineno,
+                  standalone=True), ancestor_at_indent)
+            else:
+              pytree_utils.InsertNodesAfter(_CreateCommentsFromPrefix(
+                  comment_prefix, comment_lineno,
+                  standalone=True), ancestor_at_indent)
+          else:
+            # Otherwise there are two cases.
+            #
+            # 1. The comment is on its own line
+            # 2. The comment is part of an expression.
+            #
+            # Unfortunately, it's fairly difficult to distinguish between the
+            # two in lib2to3 trees. The algorithm here is to determine whether
+            # child is the first leaf in the statement it belongs to. If it is,
+            # then the comment (which is a prefix) belongs on a separate line.
+            # If it is not, it means the comment is buried deep in the statement
+            # and is part of some expression.
+            stmt_parent = _FindStmtParent(child)
+
+            for leaf_in_parent in stmt_parent.leaves():
+              if leaf_in_parent.type == token.NEWLINE:
+                continue
+              elif id(leaf_in_parent) == id(child):
+                # This comment stands on its own line, and it has to be inserted
+                # into the appropriate parent. We'll have to find a suitable
+                # parent to insert into. See comments above
+                # _STANDALONE_LINE_NODES for more details.
+                node_with_line_parent = _FindNodeWithStandaloneLineParent(child)
+                pytree_utils.InsertNodesBefore(
+                    _CreateCommentsFromPrefix(
+                        comment_prefix, comment_lineno, standalone=True),
+                    node_with_line_parent)
+                break
+              else:
+                if comment_lineno == prev_leaf[0].lineno:
+                  comment_lines = comment_prefix.splitlines()
+                  comment_leaf = pytree.Leaf(type=token.COMMENT,
+                                             value=comment_lines[0].strip(),
+                                             context=('', (comment_lineno, 0)))
+                  pytree_utils.InsertNodesAfter([comment_leaf], prev_leaf[0])
+                  comment_prefix = '\n'.join(comment_lines[1:])
+                  comment_lineno += 1
+
+                comments = _CreateCommentsFromPrefix(comment_prefix,
+                                                     comment_lineno,
+                                                     standalone=False)
+                pytree_utils.InsertNodesBefore(comments, child)
+                break
+
+        prev_leaf[0] = child
+
+  _VisitNodeRec(tree)
+
+
+def _CreateCommentsFromPrefix(comment_prefix, comment_lineno, standalone=False):
+  """Create pytree nodes to represent the given comment prefix.
+
+  Args:
+    comment_prefix: (unicode) the text of the comment from the node's prefix.
+    comment_lineno: (int) the line number for the start of the comment.
+    standalone: (bool) determines if the comment is standalone or not.
+
+  Returns:
+    The simple_stmt nodes if this is a standalone comment, otherwise a list of
+    new COMMENT leafs. The prefix may consist of multiple comment blocks,
+    separated by blank lines. Each block gets its own leaf.
+  """
+  # The comment is stored in the prefix attribute, with no lineno of its
+  # own. So we only know at which line it ends. To find out at which line it
+  # starts, look at how many newlines the comment itself contains.
+  comments = []
+
+  lines = comment_prefix.split('\n')
+  index = 0
+  while True:
+    if index >= len(lines):
+      break
+
+    comment_block = []
+    while index < len(lines) and lines[index].lstrip().startswith('#'):
+      comment_block.append(lines[index])
+      index += 1
+
+    if comment_block:
+      new_lineno = comment_lineno + index - 1
+      comment_leaf = pytree.Leaf(type=token.COMMENT,
+                                 value='\n'.join(comment_block).strip(),
+                                 context=('', (new_lineno, 0)))
+      comment_node = comment_leaf if not standalone else pytree.Node(
+          pygram.python_symbols.simple_stmt, [comment_leaf])
+      comments.append(comment_node)
+
+    while index < len(lines) and not lines[index].lstrip():
+      index += 1
+
+  return comments
+
+# "Standalone line nodes" are tree nodes that have to start a new line in Python
+# code (and cannot follow a ';' or ':'). Other nodes, like 'expr_stmt', serve as
+# parents of other nodes but can come later in a line. This is a list of
+# standalone line nodes in the grammar. It is meant to be exhaustive
+# *eventually*, and we'll modify it with time as we discover more corner cases
+# in the parse tree.
+#
+# When splicing a standalone comment (i.e. a comment that appears on its own
+# line, not on the same line with other code), it's important to insert it into
+# an appropriate parent of the node it's attached to. An appropriate parent
+# is the first "standaline line node" in the parent chain of a node.
+_STANDALONE_LINE_NODES = frozenset(['suite', 'if_stmt', 'while_stmt',
+                                    'for_stmt', 'try_stmt', 'with_stmt',
+                                    'funcdef', 'classdef', 'decorated',
+                                    'file_input'])
+
+
+def _FindNodeWithStandaloneLineParent(node):
+  """Find a node whose parent is a 'standalone line' node.
+
+  See the comment above _STANDALONE_LINE_NODES for more details.
+
+  Arguments:
+    node: node to start from
+
+  Returns:
+    Suitable node that's either the node itself or one of its ancestors.
+  """
+  if pytree_utils.NodeName(node.parent) in _STANDALONE_LINE_NODES:
+    return node
+  else:
+    # This is guaranteed to terminate because 'file_input' is the root node of
+    # any pytree.
+    return _FindNodeWithStandaloneLineParent(node.parent)
+
+# "Statement nodes" are standalone statements. The don't have to start a new
+# line.
+_STATEMENT_NODES = frozenset(['simple_stmt']) | _STANDALONE_LINE_NODES
+
+
+def _FindStmtParent(node):
+  """Find the nearest parent of node that is a statement node.
+
+  Arguments:
+    node: node to start from
+
+  Returns:
+    Nearest parent (or node itself, if suitable).
+  """
+  if pytree_utils.NodeName(node) in _STATEMENT_NODES:
+    return node
+  else:
+    return _FindStmtParent(node.parent)
+
+
+def _FindAncestorAtIndent(node, indent):
+  """Find an ancestor of node with the given indentation.
+
+  Arguments:
+    node: node to start from. This must not be the tree root.
+    indent: indentation string for the ancestor we're looking for.
+        See _AnnotateIndents for more details.
+
+  Returns:
+    An ancestor node with suitable indentation. If no suitable ancestor is
+    found, the closest ancestor to the tree root is returned.
+  """
+  if node.parent.parent is None:
+    # Our parent is the tree root, so there's nowhere else to go.
+    return node
+  else:
+    # If the parent has an indent annotation, and it's shorter than node's
+    # indent, this is a suitable ancestor.
+    # The reason for "shorter" rather than "equal" is that comments may be
+    # improperly indented (i.e. by three spaces, where surrounding statements
+    # have either zero or two or four), and we don't want to propagate them all
+    # the way to the root.
+    parent_indent = pytree_utils.GetNodeAnnotation(
+        node.parent, pytree_utils.Annotation.CHILD_INDENT)
+    if parent_indent is not None and indent.startswith(parent_indent):
+      return node
+    else:
+      # Keep looking up the tree.
+      return _FindAncestorAtIndent(node.parent, indent)
+
+
+def _AnnotateIndents(tree):
+  """Annotate the tree with child_indent annotations.
+
+  A child_indent annotation on a node specifies the indentation (as a string,
+  like "  ") of its children. It is inferred from the INDENT child of a node.
+
+  Arguments:
+    tree: root of a pytree. The pytree is modified to add annotations to nodes.
+
+  Raises:
+    RuntimeError: if the tree is malformed.
+  """
+  # Annotate the root of the tree with zero indent.
+  if tree.parent is None:
+    pytree_utils.SetNodeAnnotation(tree, pytree_utils.Annotation.CHILD_INDENT,
+                                   '')
+  for child in tree.children:
+    if child.type == token.INDENT:
+      child_indent = pytree_utils.GetNodeAnnotation(
+          tree, pytree_utils.Annotation.CHILD_INDENT)
+      if child_indent is not None and child_indent != child.value:
+        raise RuntimeError('inconsistent indentation for child', (tree, child))
+      pytree_utils.SetNodeAnnotation(tree, pytree_utils.Annotation.CHILD_INDENT,
+                                     child.value)
+    _AnnotateIndents(child)
diff --git a/yapf/yapflib/file_resources.py b/yapf/yapflib/file_resources.py
new file mode 100644
index 0000000..d047a53
--- /dev/null
+++ b/yapf/yapflib/file_resources.py
@@ -0,0 +1,77 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Interface to file resources.
+
+This module provides functions for interfacing with files: opening, writing, and
+querying.
+"""
+
+import io
+import os
+import sys
+
+
+def GetCommandLineFiles(command_line_file_list, recursive):
+  """Return the list of files specified on the command line."""
+  return _FindFiles(command_line_file_list, recursive)
+
+
+def WriteReformattedCode(filename, reformatted_code, in_place):
+  """Emit the reformatted code.
+
+  Write the reformatted code into the file, if in_place is True. Otherwise,
+  write to stdout.
+
+  Arguments:
+    filename: (unicode) The name of the unformatted file.
+    reformatted_code: (unicode) The reformatted code.
+    in_place: (bool) If True, then write the reformatted code to the file.
+  """
+  if not reformatted_code.strip():
+    return
+  if in_place:
+    with io.open(filename, mode='w', newline='') as fd:
+      fd.write(reformatted_code)
+  else:
+    # Re-encode the text so that if we pipe the output to a file, it will
+    # have the proper encoding. Otherwise, we'll get a UnicodeEncodeError
+    # exception.
+    reformatted_code = reformatted_code.encode('UTF-8')
+    sys.stdout.write(reformatted_code)
+
+
+def _FindFiles(filenames, recursive):
+  """Find all Python files."""
+  python_files = []
+  for filename in filenames:
+    if os.path.isdir(filename):
+      if recursive:
+        # TODO(morbo): Look into a version of os.walk that can handle recursion.
+        python_files.extend(os.path.join(dirpath, f)
+                            for dirpath, _, filelist in os.walk(filename)
+                            for f in filelist
+                            if IsPythonFile(os.path.join(dirpath, f)))
+      else:
+        python_files.extend(os.path.join(filename, f)
+                            for f in os.listdir(filename)
+                            if IsPythonFile(os.path.join(filename, f)))
+    elif os.path.isfile(filename) and IsPythonFile(filename):
+      python_files.append(filename)
+
+  return python_files
+
+
+def IsPythonFile(filename):
+  """Return True if filename is a Python file."""
+  return os.path.splitext(filename)[1] == '.py'
diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py
new file mode 100644
index 0000000..67b60ea
--- /dev/null
+++ b/yapf/yapflib/format_decision_state.py
@@ -0,0 +1,388 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Implements a format decision state object that manages whitespace decisions.
+
+Each token is processed one at a time, at which point its whitespace formatting
+decisions are made. A graph of potential whitespace formattings is created,
+where each node in the graph is a format decision state object. The heuristic
+tries formatting the token with and without a newline before it to determine
+which one has the least penalty. Therefore, the format decision state object for
+each decision needs to be its own unique copy.
+
+Once the heuristic determines the best formatting, it makes a non-dry run pass
+through the code to commit the whitespace formatting.
+
+  FormatDecisionState: main class exported by this module.
+"""
+
+import copy
+
+from yapf.yapflib import format_token
+from yapf.yapflib import split_penalty
+from yapf.yapflib import style
+
+
+class FormatDecisionState(object):
+  """The current state when indenting an unwrapped line.
+
+  The FormatDecisionState object is meant to be copied instead of referenced.
+
+  Attributes:
+    first_indent: The indent of the first token.
+    column: The number of used columns in the current line.
+    next_token: The next token to be formatted.
+    paren_level: The level of nesting inside (), [], and {}.
+    start_of_line_level: The paren_level at the start of this line.
+    lowest_level_on_line: The lowest paren_level on the current line.
+    newline: Indicates if a newline is added along the edge to this format
+      decision state node.
+    previous: The previous format decision state in the decision tree.
+    stack: A stack (of _ParenState) keeping track of properties applying to
+      parenthesis levels.
+    ignore_stack_for_comparison: Ignore the stack of _ParenState for state
+      comparison.
+  """
+
+  def __init__(self, line, first_indent):
+    """Initializer.
+
+    Initializes to the state after placing the first token from 'line' at
+    'first_indent'.
+
+    Arguments:
+      line: (UnwrappedLine) The unwrapped line we're currently processing.
+      first_indent: (int) The indent of the first token.
+    """
+    self.next_token = line.first
+    self.column = first_indent
+    self.paren_level = 0
+    self.start_of_line_level = 0
+    self.lowest_level_on_line = 0
+    self.ignore_stack_for_comparison = False
+    self.stack = [_ParenState(first_indent, first_indent)]
+    self.first_indent = first_indent
+    self.newline = False
+    self.previous = None
+    self._MoveStateToNextToken()
+
+  def Clone(self):
+    new = copy.copy(self)
+    new.stack = copy.deepcopy(self.stack)
+    return new
+
+  def __eq__(self, other):
+    # Note: 'first_indent' is implicit in the stack. Also, we ignore 'previous',
+    # because it shouldn't have a bearing on this comparison. (I.e., it will
+    # report equal if 'next_token' does.)
+    return (self.next_token == other.next_token and
+            self.column == other.column and
+            self.paren_level == other.paren_level and
+            self.start_of_line_level == other.start_of_line_level and
+            self.lowest_level_on_line == other.lowest_level_on_line and
+            (self.ignore_stack_for_comparison or
+             other.ignore_stack_for_comparison or self.stack == other.stack))
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __hash__(self):
+    return hash((self.next_token, self.column, self.paren_level,
+                 self.start_of_line_level, self.lowest_level_on_line))
+
+  def __repr__(self):
+    return ('column::%d, next_token::%s, paren_level::%d, stack::[\n\t%s' %
+            (self.column, repr(self.next_token), self.paren_level,
+             '\n\t'.join(repr(s) for s in self.stack) + ']'))
+
+  def CanSplit(self):
+    """Returns True if the line can be split before the next token."""
+    current = self.next_token
+
+    if not current.can_break_before:
+      return False
+
+    return True
+
+  def MustSplit(self):
+    """Returns True if the line must split before the next token."""
+    current = self.next_token
+    previous_token = current.previous_token
+    next_token = current.next_token
+
+    if current.must_break_before:
+      return True
+
+    if (self.stack[-1].split_before_closing_bracket and
+        # FIXME(morbo): Use the 'matching_bracket' instead of this.
+        # FIXME(morbo): Don't forget about tuples!
+        current.value in ']}'):
+      # Split if we need to split before the closing bracket and the next
+      # token is a closing bracket.
+      return True
+
+    if previous_token:
+      length = _GetLengthToMatchingParen(previous_token)
+      if (previous_token.value == '{' and  # TODO(morbo): List initializers?
+          length + self.column > style.COLUMN_LIMIT):
+        return True
+
+      # TODO(morbo): This should be controlled with a knob.
+      if (current.subtype == format_token.Subtype.DICTIONARY_KEY and
+          not current.is_comment):
+        # Place each dictionary entry on its own line.
+        return True
+
+      # TODO(morbo): This should be controlled with a knob.
+      if current.subtype == format_token.Subtype.DICT_SET_GENERATOR:
+        return True
+
+      if (next_token and previous_token.value != '(' and
+          next_token.subtype ==
+          format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN and
+          next_token.node_split_penalty < split_penalty.UNBREAKABLE):
+        return style.SPLIT_BEFORE_NAMED_ASSIGNS
+
+    return False
+
+  def AddTokenToState(self, newline, dry_run, must_split=False):
+    """Add a token to the format decision state.
+
+    Allow the heuristic to try out adding the token with and without a newline.
+    Later on, the algorithm will determine which one has the lowest penalty.
+
+    Arguments:
+      newline: (bool) Add the token on a new line if True.
+      dry_run: (bool) Don't commit whitespace changes to the FormatToken if
+        True.
+      must_split: (bool) A newline was required before this token.
+
+    Returns:
+      The penalty of splitting after the current token.
+    """
+    if not self.stack:
+      self.column = (self.next_token.spaces_required_before +
+                     len(self.next_token.value))
+      self.next_token = self.next_token.next_token
+      return 0
+
+    penalty = 0
+    if newline:
+      penalty = self._AddTokenOnNewline(dry_run, must_split)
+    else:
+      self._AddTokenOnCurrentLine(dry_run)
+
+    return self._MoveStateToNextToken() + penalty
+
+  def _AddTokenOnCurrentLine(self, dry_run):
+    """Puts the token on the current line.
+
+    Appends the next token to the state and updates information necessary for
+    indentation.
+
+    Arguments:
+      dry_run: (bool) Commit whitespace changes to the FormatToken if True.
+    """
+    current = self.next_token
+    previous = current.previous_token
+
+    spaces = current.spaces_required_before
+    if not dry_run:
+      current.AddWhitespacePrefix(newlines_before=0, spaces=spaces)
+
+    if previous.OpensScope():
+      if not current.is_comment:
+        # Align closing scopes that are on a newline with the opening scope:
+        #
+        #     foo = [a,
+        #            b,
+        #           ]
+        self.stack[-1].closing_scope_indent = previous.column
+        self.stack[-1].indent = self.column + spaces
+      else:
+        self.stack[-1].closing_scope_indent = (
+            self.stack[-1].indent - style.CONTINUATION_INDENT_WIDTH)
+
+    self.column += spaces
+
+  def _AddTokenOnNewline(self, dry_run, must_split):
+    """Adds a line break and necessary indentation.
+
+    Appends the next token to the state and updates information necessary for
+    indentation.
+
+    Arguments:
+      dry_run: (bool) Don't commit whitespace changes to the FormatToken if
+        True.
+      must_split: (bool) A newline was required before this token.
+
+    Returns:
+      The split penalty for splitting after the current state.
+    """
+    current = self.next_token
+    previous = current.previous_token
+
+    self.column = self._GetNewlineColumn()
+
+    if not dry_run:
+      current.AddWhitespacePrefix(newlines_before=1, spaces=self.column)
+
+    if not current.is_comment:
+      self.stack[-1].last_space = self.column
+    self.start_of_line_level = self.paren_level
+    self.lowest_level_on_line = self.paren_level
+
+    # Any break on this level means that the parent level has been broken and we
+    # need to avoid bin packing there.
+    for paren_state in self.stack:
+      paren_state.split_before_parameter = True
+
+    if (previous.value != ',' and not previous.is_binary_op and
+        not current.is_binary_op and not previous.OpensScope()):
+      self.stack[-1].split_before_parameter = True
+
+    if (previous.OpensScope() or
+        (previous.is_comment and previous.previous_token is not None and
+         previous.previous_token.OpensScope())):
+      self.stack[-1].closing_scope_indent = (
+          max(0, self.stack[-1].indent - style.CONTINUATION_INDENT_WIDTH))
+      self.stack[-1].split_before_closing_bracket = True
+
+    # Calculate the split penalty.
+    penalty = current.split_penalty
+
+    # Add a penalty for each increasing newline we add.
+    last = self.stack[-1]
+    penalty += style.SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT * last.num_line_splits
+    if not must_split:
+      # Don't penalize for a must split.
+      last.num_line_splits += 1
+
+    return penalty + 10
+
+  def _GetNewlineColumn(self):
+    """Return the new column on the newline."""
+    current = self.next_token
+    top_of_stack = self.stack[-1]
+
+    if current.OpensScope():
+      return self.first_indent if not self.paren_level else top_of_stack.indent
+
+    if current.ClosesScope():
+      return top_of_stack.closing_scope_indent
+
+    return top_of_stack.indent
+
+  def _MoveStateToNextToken(self):
+    """Calculate format decision state information and move onto the next token.
+
+    Before moving onto the next token, we first calculate the format decision
+    state given the current token and its formatting decisions. Then the format
+    decision state is set up so that the next token can be added.
+
+    Returns:
+      The penalty for the number of characters over the column limit.
+    """
+    current = self.next_token
+    if not current.OpensScope() and not current.ClosesScope():
+      self.lowest_level_on_line = min(self.lowest_level_on_line,
+                                      self.paren_level)
+
+    # If we encounter an opening bracket, we add a level to our stack to prepare
+    # for the subsequent tokens.
+    if current.OpensScope():
+      last = self.stack[-1]
+      new_indent = style.CONTINUATION_INDENT_WIDTH + last.last_space
+
+      self.stack.append(_ParenState(new_indent, self.stack[-1].last_space))
+      self.stack[-1].break_before_paremeter = False
+      self.paren_level += 1
+
+    # If we encounter a closing bracket, we can remove a level from our
+    # parenthesis stack.
+    if len(self.stack) > 1 and current.ClosesScope():
+      self.stack.pop()
+      self.paren_level -= 1
+
+    is_multiline_string = current.is_string and '\n' in current.value
+    if is_multiline_string:
+      # This is a multiline string. Only look at the first line.
+      self.column += len(current.value.split('\n')[0])
+    else:
+      self.column += len(current.value)
+
+    self.next_token = self.next_token.next_token
+
+    # Calculate the penalty for overflowing the column limit.
+    penalty = 0
+    if self.column > style.COLUMN_LIMIT:
+      excess_characters = self.column - style.COLUMN_LIMIT
+      penalty = style.SPLIT_PENALTY_EXCESS_CHARACTER * excess_characters
+
+    if is_multiline_string:
+      # If this is a multiline string, the column is actually the
+      # end of the last line in the string.
+      self.column = len(current.value.split('\n')[-1])
+
+    return penalty
+
+
+def _GetLengthToMatchingParen(token):
+  """Returns the length from one bracket to the matching bracket.
+
+  Arguments:
+    token: (FormatToken) The opening bracket token.
+
+  Returns:
+    The length to the closing paren or up to the first point where we can split
+    the line. The length includes the brackets.
+  """
+  if not token.matching_bracket:
+    return 0
+  end = token.matching_bracket
+  while end.next_token and not end.next_token.can_break_before:
+    end = end.next_token
+  return end.total_length - token.total_length + 1
+
+
+class _ParenState(object):
+  """Maintains the state of the bracket enclosures.
+
+  A stack of _ParenState objects are kept so that we know how to indent relative
+  to the brackets.
+
+  Attributes:
+    indent: The column position to which a specified parenthesis level needs to
+      be indented.
+    last_space: The column position of the last space on each level.
+    split_before_closing_bracket: Whether a newline needs to be inserted before
+      the closing bracket. We only want to insert a newline before the closing
+      bracket if there also was a newline after the beginning left bracket.
+    split_before_parameter: Split the line after the next comma.
+    num_line_splits: Number of line splits this _ParenState contains already.
+      Each subsequent line split gets an increasing penalty.
+  """
+
+  # TODO(morbo): This doesn't track "bin packing."
+
+  def __init__(self, indent, last_space):
+    self.indent = indent
+    self.last_space = last_space
+    self.closing_scope_indent = 0
+    self.split_before_closing_bracket = False
+    self.split_before_parameter = False
+    self.num_line_splits = 0
+
+  def __repr__(self):
+    return '[indent::%d, last_space::%d, closing_scope_indent::%d]' % (
+        self.indent, self.last_space, self.closing_scope_indent)
diff --git a/yapf/yapflib/format_token.py b/yapf/yapflib/format_token.py
new file mode 100644
index 0000000..69f1e98
--- /dev/null
+++ b/yapf/yapflib/format_token.py
@@ -0,0 +1,211 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Pytree nodes with extra formatting information.
+
+This is a thin wrapper around a pytree.Leaf node.
+"""
+
+import keyword
+import re
+
+from lib2to3 import pytree
+from lib2to3.pgen2 import token
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import style
+
+
+class Subtype(object):
+  """Subtype information about tokens.
+
+  Gleaned from parsing the code. Helps determine the best formatting.
+  """
+  NONE = 0
+  UNARY_OPERATOR = 1
+  BINARY_OPERATOR = 2
+  SUBSCRIPT_COLON = 3
+  DEFAULT_OR_NAMED_ASSIGN = 4
+  VARARGS_STAR = 5
+  KWARGS_STAR_STAR = 6
+  ASSIGN_OPERATOR = 7
+  DICTIONARY_KEY = 8
+  DICT_SET_GENERATOR = 9
+
+
+class FormatToken(object):
+  """A wrapper around pytree Leaf nodes.
+
+  This represents the token plus additional information useful for reformatting
+  the code.
+
+  Attributes:
+    next_token: The token in the unwrapped line after this token or None if this
+      is the last token in the unwrapped line.
+    previous_token: The token in the unwrapped line before this token or None if
+      this is the first token in the unwrapped line.
+    matching_bracket: If a bracket token ('[', '{', or '(') the matching
+      bracket.
+    whitespace_prefix: The prefix for the whitespace.
+    spaces_required_before: The number of spaces required before a token. This
+      is a lower-bound for the formatter and not a hard requirement. For
+      instance, a comment may have n required spaces before it. But the
+      formatter won't place n spaces before all comments. Only those that are
+      moved to the end of a line of code. The formatter may use different
+      spacing when appropriate.
+    can_break_before: True if we're allowed to break before this token.
+    must_break_before: True if we're required to break before this token.
+    total_length: The total length of the unwrapped line up to and including
+      whitespace and this token. However, this doesn't include the initial
+      indentation amount.
+    split_penalty: The penalty for splitting the line before this token.
+  """
+
+  def __init__(self, node):
+    """Constructor.
+
+    Arguments:
+      node: (pytree.Leaf) The node that's being wrapped.
+    """
+    assert isinstance(node, pytree.Leaf)
+    self._node = node
+    self.next_token = None
+    self.previous_token = None
+    self.matching_bracket = None
+    self.whitespace_prefix = ''
+    self.can_break_before = False
+    self.must_break_before = False
+    self.total_length = 0  # TODO(morbo): Think up a better name.
+    self.split_penalty = 0
+
+    if self.is_comment:
+      self.spaces_required_before = style.SPACES_BEFORE_COMMENT
+    else:
+      self.spaces_required_before = 0
+
+  def AddWhitespacePrefix(self, newlines_before, spaces=0, indent_level=0):
+    """Register a token's whitespace prefix.
+
+    This is the whitespace that will be output before a token's string.
+
+    Arguments:
+      newlines_before: (int) The number of newlines to place before the token.
+      spaces: (int) The number of spaces to place before the token.
+      indent_level: (int) The indentation level.
+    """
+    spaces_before = ' ' * indent_level * style.INDENT_WIDTH + ' ' * spaces
+
+    if self.is_comment:
+      comment_lines = [s.lstrip() for s in self.value.splitlines()]
+      self._node.value = ('\n' + spaces_before).join(comment_lines)
+
+    self.whitespace_prefix = ('\n' * (self.newlines or newlines_before) +
+                              spaces_before)
+
+  def AdjustNewlinesBefore(self, newlines_before):
+    """Change the number of newlines before this token."""
+    self.whitespace_prefix = ('\n' * newlines_before +
+                              self.whitespace_prefix.lstrip('\n'))
+
+  def OpensScope(self):
+    return self.value in pytree_utils.OPENING_BRACKETS
+
+  def ClosesScope(self):
+    return self.value in pytree_utils.CLOSING_BRACKETS
+
+  def GetPytreeNode(self):
+    return self._node
+
+  @property
+  def token_type(self):
+    return self._node.type
+
+  @property
+  def value(self):
+    return self._node.value
+
+  @property
+  def node_split_penalty(self):
+    """Split penalty attached to the pytree node of this token.
+
+    Returns:
+      The penalty, or None if no annotation is attached.
+    """
+    return pytree_utils.GetNodeAnnotation(self._node,
+                                          pytree_utils.Annotation.SPLIT_PENALTY)
+
+  @property
+  def newlines(self):
+    """The number of newlines needed before this token."""
+    return pytree_utils.GetNodeAnnotation(self._node,
+                                          pytree_utils.Annotation.NEWLINES)
+
+  @property
+  def column(self):
+    """The original column number of the node in the source."""
+    return self._node.column
+
+  @property
+  def lineno(self):
+    """The original line number of the node in the source."""
+    return self._node.lineno
+
+  @property
+  def subtype(self):
+    """Extra type information for directing formatting."""
+    value = pytree_utils.GetNodeAnnotation(self._node,
+                                           pytree_utils.Annotation.SUBTYPE)
+    return Subtype.NONE if value is None else value
+
+  @property
+  def is_binary_op(self):
+    """Token is a binary operator."""
+    return self.subtype == Subtype.BINARY_OPERATOR
+
+  @property
+  def name(self):
+    """A string representation of the node's name."""
+    return pytree_utils.NodeName(self._node)
+
+  def __repr__(self):
+    return 'FormatToken(name={0}, value={1})'.format(self.name, self.value)
+
+  @property
+  def is_comment(self):
+    return self._node.type == token.COMMENT
+
+  @property
+  def is_keyword(self):
+    return keyword.iskeyword(self.value)
+
+  @property
+  def is_name(self):
+    return self._node.type == token.NAME and not self.is_keyword
+
+  @property
+  def is_operator(self):
+    return self._node.value in {'+', '-', '*', '/', '//', '**'}
+
+  @property
+  def is_number(self):
+    return self._node.type == token.NUMBER
+
+  @property
+  def is_string(self):
+    return self._node.type == token.STRING
+
+  @property
+  def is_docstring(self):
+    return (self.is_string and
+            re.match(r'^[uUbB]?[rR]?(?P<delim>"""|\'\'\').*(?P=delim)$',
+                     self.value, re.DOTALL) is not None)
diff --git a/yapf/yapflib/line_joiner.py b/yapf/yapflib/line_joiner.py
new file mode 100644
index 0000000..72e7ffe
--- /dev/null
+++ b/yapf/yapflib/line_joiner.py
@@ -0,0 +1,107 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Join unwrapped lines together.
+
+Determine how many lines can be joined into one line. For instance, we could
+join these statements into one line:
+
+  if a == 42:
+    continue
+
+like this:
+
+  if a == 42: continue
+
+There are a few restrictions:
+
+  1. The lines should have been joined in the original source.
+  2. The joined lines must not go over the column boundary if placed on the same
+     line.
+  3. They need to be very simple statements.
+
+Note: Because we don't allow the use of a semicolon to separate statements, it
+follows that there can only be at most two lines to join.
+"""
+
+from yapf.yapflib import style
+
+_CLASS_OR_FUNC = frozenset({'def', 'class'})
+_COMPOUND_STMT = frozenset({'def', 'class', 'if', 'for', 'with', 'while'})
+
+
+def CanMergeMultipleLines(lines):
+  """Determine if multiple lines can be joined into one.
+
+  Arguments:
+    lines: (list of UnwrappedLine) This is a splice of UnwrappedLines from the
+      full code base.
+
+  Returns:
+    True if two consecutive lines can be joined together. In reality, this will
+    only happen if two consecutive lines can be joined, due to the style guide.
+  """
+  # The indentation amount for the starting line (number of spaces).
+  indent_amt = lines[0].depth * style.INDENT_WIDTH
+  if len(lines) == 1 or indent_amt > style.COLUMN_LIMIT:
+    return False
+
+  if (len(lines) >= 3 and lines[2].depth >= lines[1].depth and
+      lines[0].depth != lines[2].depth):
+    # If lines[2]'s depth is greater than or equal to line[1]'s depth, we're not
+    # looking at a single statement (e.g., if-then, while, etc.). A following
+    # line with the same depth as the first line isn't part of the lines we
+    # would want to combine.
+    return False  # Don't merge more than two lines together.
+
+  if lines[0].first.value in _CLASS_OR_FUNC:
+    # Don't join lines onto the starting line of a class or function.
+    return False
+
+  limit = style.COLUMN_LIMIT - indent_amt
+  if lines[0].last.total_length < limit:
+    limit -= lines[0].last.total_length
+
+    if lines[0].first.value == 'if':
+      return _CanMergeLineIntoIfStatement(lines, limit)
+
+  # TODO(morbo): Other control statements?
+
+  return False
+
+
+def _CanMergeLineIntoIfStatement(lines, limit):
+  """Determine if we can merge a short if-then statement into one line.
+
+  Two lines of an if-then statement can be merged if they were that way in the
+  original source, fit on the line without going over the column limit, and are
+  considered "simple" statements --- typically statements like 'pass',
+  'continue', and 'break'.
+
+  Arguments:
+    lines: (list of UnwrappedLine) The lines we are wanting to merge.
+    limit: (int) The amount of space remaining on the line.
+
+  Returns:
+    True if the lines can be merged, False otherwise.
+  """
+  if lines[0].lineno != lines[1].lineno:
+    # Don't merge lines if the original lines weren't merged.
+    return False
+  if lines[1].is_comment:
+    return False
+  if lines[1].last.total_length >= limit:
+    return False
+  if lines[1].first.value in _COMPOUND_STMT:
+    return False
+  return True
diff --git a/yapf/yapflib/pytree_unwrapper.py b/yapf/yapflib/pytree_unwrapper.py
new file mode 100644
index 0000000..004ce50
--- /dev/null
+++ b/yapf/yapflib/pytree_unwrapper.py
@@ -0,0 +1,250 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""PyTreeUnwrapper - produces a list of unwrapped lines from a pytree.
+
+[for a description of what an unwrapped line is, see unwrapped_line.py]
+
+This is a pytree visitor that goes over a parse tree and produces a list of
+UnwrappedLine containers from it, each with its own depth and containing all
+the tokens that could fit on the line if there were no maximal line-length
+limitations.
+
+Note: a precondition to running this visitor and obtaining correct results is
+for the tree to have its comments spliced in as nodes. Prefixes are ignored.
+
+For most uses, the convenience function UnwrapPyTree should be sufficient.
+"""
+
+# The word "token" is overloaded within this module, so for clarity rename
+# the imported pgen2.token module.
+from lib2to3.pgen2 import token as grammar_token
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import split_penalty
+from yapf.yapflib import unwrapped_line
+
+
+def UnwrapPyTree(tree):
+  """Create and return a list of unwrapped lines from the given pytree.
+
+  Arguments:
+    tree: the top-level pytree node to unwrap.
+
+  Returns:
+    A list of UnwrappedLine objects.
+  """
+  unwrapper = PyTreeUnwrapper()
+  unwrapper.Visit(tree)
+  uwlines = unwrapper.GetUnwrappedLines()
+  uwlines.sort(key=lambda x: x.lineno)
+  return uwlines
+
+# Grammar tokens considered as whitespace for the purpose of unwrapping.
+_WHITESPACE_TOKENS = frozenset([grammar_token.NEWLINE, grammar_token.DEDENT,
+                                grammar_token.INDENT, grammar_token.ENDMARKER])
+
+
+class PyTreeUnwrapper(pytree_visitor.PyTreeVisitor):
+  """PyTreeUnwrapper - see file-level docstring for detailed description.
+
+  Note: since this implements PyTreeVisitor and node names in lib2to3 are
+  underscore_separated, the visiting methods of this class are named as
+  Visit_node_name. invalid-name pragmas are added to each such method to silence
+  a style warning. This is forced on us by the usage of lib2to3, and re-munging
+  method names to make them different from actual node names sounded like a
+  confusing and brittle affair that wasn't worth it for this small & controlled
+  deviation from the style guide.
+
+  To understand the connection between visitor methods in this class, some
+  familiarity with the Python grammar is required.
+  """
+
+  def __init__(self):
+    # A list of all unwrapped lines finished visiting so far.
+    self._unwrapped_lines = []
+
+    # Builds up a "current" unwrapped line while visiting pytree nodes. Some
+    # nodes will finish a line and start a new one.
+    self._cur_unwrapped_line = unwrapped_line.UnwrappedLine(0)
+
+    # Current indentation depth.
+    self._cur_depth = 0
+
+  def GetUnwrappedLines(self):
+    """Fetch the result of the tree walk.
+
+    Note: only call this after visiting the whole tree.
+
+    Returns:
+      A list of UnwrappedLine objects.
+    """
+    # Make sure the last line that was being populated is flushed.
+    self._StartNewLine()
+    return self._unwrapped_lines
+
+  def _StartNewLine(self):
+    """Finish current line and start a new one.
+
+    Place the currently accumulated line into the _unwrapped_lines list and
+    start a new one.
+    """
+    if self._cur_unwrapped_line.tokens:
+      self._unwrapped_lines.append(self._cur_unwrapped_line)
+      _MatchBrackets(self._cur_unwrapped_line)
+      _AdjustSplitPenalty(self._cur_unwrapped_line)
+    self._cur_unwrapped_line = unwrapped_line.UnwrappedLine(self._cur_depth)
+
+  # pylint: disable=invalid-name,missing-docstring
+  def Visit_simple_stmt(self, node):
+    # A 'simple_stmt' conveniently represents a non-compound Python statement,
+    # i.e. a statement that does not contain other statements.
+
+    # When compound nodes have a single statement as their suite, the parser
+    # can leave it in the tree directly without creating a suite. But we have
+    # to increase depth in these cases as well. However, don't increase the
+    # depth of we have a simple_stmt that's a comment node. This represents a
+    # standalone comment and in the case of it coming directly after the
+    # funcdef, it is a "top" comment for the whole function.
+    # TODO(eliben): add more relevant compound statements here.
+    single_stmt_suite = (node.parent and
+                         pytree_utils.NodeName(node.parent) == 'funcdef')
+    is_comment_stmt = pytree_utils.NodeName(node.children[0]) == 'COMMENT'
+    if single_stmt_suite and not is_comment_stmt:
+      self._cur_depth += 1
+    self._StartNewLine()
+    self.DefaultNodeVisit(node)
+    if single_stmt_suite and not is_comment_stmt:
+      self._cur_depth -= 1
+
+  def _VisitCompoundStatement(self, node, substatement_names):
+    """Helper for visiting compound statements.
+
+    Python compound statements serve as containers for other statements. Thus,
+    when we encounter a new compound statement we start a new unwrapped line.
+
+    Arguments:
+      node: the node to visit.
+      substatement_names: set of node names. A compound statement will be
+        recognized as a NAME node with a name in this set.
+    """
+    for child in node.children:
+      # A pytree is structured in such a way that a single 'if_stmt' node will
+      # contain all the 'if', 'elif' and 'else' nodes as children (similar
+      # structure applies to 'while' statements, 'try' blocks, etc). Therefore,
+      # we visit all children here and create a new line before the requested
+      # set of nodes.
+      if (child.type == grammar_token.NAME and
+          child.value in substatement_names):
+        self._StartNewLine()
+      self.Visit(child)
+
+  def Visit_if_stmt(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'if', 'else', 'elif'})
+
+  def Visit_while_stmt(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'while', 'else'})
+
+  def Visit_for_stmt(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'for', 'else'})
+
+  def Visit_try_stmt(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'try', 'except', 'else', 'finally'})
+
+  def Visit_except_clause(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'except'})
+
+  def Visit_funcdef(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'def'})
+
+  def Visit_classdef(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'class'})
+
+  def Visit_decorators(self, node):  # pylint: disable=invalid-name
+    for child in node.children:
+      self._StartNewLine()
+      self.Visit(child)
+
+  def Visit_decorated(self, node):  # pylint: disable=invalid-name
+    for child in node.children:
+      self._StartNewLine()
+      self.Visit(child)
+
+  def Visit_with_stmt(self, node):  # pylint: disable=invalid-name
+    self._VisitCompoundStatement(node, {'with'})
+
+  def Visit_suite(self, node):  # pylint: disable=invalid-name
+    # A 'suite' starts a new indentation level in Python.
+    self._cur_depth += 1
+    self._StartNewLine()
+    self.DefaultNodeVisit(node)
+    self._cur_depth -= 1
+
+  def DefaultLeafVisit(self, leaf):
+    """Default visitor for tree leaves.
+
+    A tree leaf is always just gets appended to the current unwrapped line.
+
+    Arguments:
+      leaf: the leaf to visit.
+    """
+    if (leaf.type not in _WHITESPACE_TOKENS and
+        (leaf.type != grammar_token.COMMENT or leaf.value.strip())):
+      # Add non-whitespace tokens and comments that aren't empty.
+      self._cur_unwrapped_line.AppendNode(leaf)
+
+
+_BRACKET_MATCH = {')': '(', '}': '{', ']': '['}
+
+
+def _MatchBrackets(uwline):
+  """Visit the node and match the brackets.
+
+  For every open bracket ('[', '{', or '('), find the associated closing bracket
+  and "match" them up. I.e., save in the token a pointer to its associated open
+  or close bracket.
+
+  Arguments:
+    uwline: (UnwrappedLine) An unwrapped line.
+  """
+  bracket_stack = []
+  for token in uwline.tokens:
+    if token.value in pytree_utils.OPENING_BRACKETS:
+      bracket_stack.append(token)
+    elif token.value in pytree_utils.CLOSING_BRACKETS:
+      assert _BRACKET_MATCH[token.value] == bracket_stack[-1].value
+      bracket_stack[-1].matching_bracket = token
+      token.matching_bracket = bracket_stack[-1]
+      bracket_stack.pop()
+
+
+def _AdjustSplitPenalty(uwline):
+  """Visit the node and adjust the split penalties if needed.
+
+  A token shouldn't be split if it's not within a bracket pair. Mark any token
+  that's not within a bracket pair as "unbreakable".
+
+  Arguments:
+    uwline: (UnwrappedLine) An unwrapped line.
+  """
+  bracket_level = 0
+  for index, token in enumerate(uwline.tokens):
+    if index and not bracket_level:
+      pytree_utils.SetNodeAnnotation(token.GetPytreeNode(),
+                                     pytree_utils.Annotation.SPLIT_PENALTY,
+                                     split_penalty.UNBREAKABLE)
+    if token.value in pytree_utils.OPENING_BRACKETS:
+      bracket_level += 1
+    elif token.value in pytree_utils.CLOSING_BRACKETS:
+      bracket_level -= 1
diff --git a/yapf/yapflib/pytree_utils.py b/yapf/yapflib/pytree_utils.py
new file mode 100644
index 0000000..624c55c
--- /dev/null
+++ b/yapf/yapflib/pytree_utils.py
@@ -0,0 +1,216 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""pytree-related utilities.
+
+This module collects various utilities related to the parse trees produced by
+the lib2to3 library.
+
+  NodeName(): produces a string name for pytree nodes.
+  ParseCodeToTree(): convenience wrapper around lib2to3 interfaces to parse
+                     a given string with code to a pytree.
+  InsertNodeBefore(): insert a node before another in a pytree.
+  InsertNodeAfter(): insert a node after another in a pytree.
+  {Get,Set}NodeAnnotation(): manage custom annotations on pytree nodes.
+"""
+
+from lib2to3 import pygram
+from lib2to3 import pytree
+from lib2to3.pgen2 import driver
+from lib2to3.pgen2 import parse
+from lib2to3.pgen2 import token
+
+# TODO(eliben): We may want to get rid of this filtering at some point once we
+# have a better understanding of what information we need from the tree. Then,
+# these tokens may be filtered out from the tree before the tree gets to the
+# unwrapper.
+NONSEMANTIC_TOKENS = frozenset(['DEDENT', 'INDENT', 'NEWLINE', 'ENDMARKER'])
+
+OPENING_BRACKETS = frozenset({'(', '[', '{'})
+CLOSING_BRACKETS = frozenset({')', ']', '}'})
+
+
+class Annotation(object):
+  """Annotation names associated with pytrees."""
+  CHILD_INDENT = 'child_indent'
+  NEWLINES = 'newlines'
+  SPLIT_PENALTY = 'split_penalty'
+  SUBTYPE = 'subtype'
+
+
+def NodeName(node):
+  """Produce a string name for a given node.
+
+  For a Leaf this is the token name, and for a Node this is the type.
+
+  Arguments:
+    node: a tree node
+
+  Returns:
+    Name as a string.
+  """
+  # Nodes with values < 256 are tokens. Values >= 256 are grammar symbols.
+  if node.type < 256:
+    return token.tok_name[node.type]
+  else:
+    return pygram.python_grammar.number2symbol[node.type]
+
+
+def ParseCodeToTree(code):
+  """Parse the given code to a lib2to3 pytree.
+
+  Arguments:
+    code: a string with the code to parse.
+
+  Returns:
+    The root node of the parsed tree.
+  """
+  # This function is tiny, but the incantation for invoking the parser correctly
+  # is sufficiently magical to be worth abstracting away.
+  try:
+    # Try to parse the code treating 'print' as a function call (3.0 behavior).
+    parser_driver = driver.Driver(pygram.python_grammar_no_print_statement,
+                                  convert=pytree.convert)
+    tree = parser_driver.parse_string(code, debug=False)
+  except parse.ParseError:
+    # Treating 'print' as a function call failed. Now try to parse the code
+    # with 'print' as a statement (pre-3.0 behavior). If this fails, then
+    # there's something else wrong with the code.
+    parser_driver = driver.Driver(pygram.python_grammar, convert=pytree.convert)
+    tree = parser_driver.parse_string(code, debug=False)
+  return tree
+
+
+def InsertNodesBefore(new_nodes, target):
+  """Insert new_nodes before the given target location in the tree.
+
+  Arguments:
+    new_nodes: a sequence of new nodes to insert (the nodes should not be in the
+      tree).
+    target: the target node before which the new node node will be inserted.
+
+  Raises:
+    RuntimeError: if the tree is corrupted, or the insertion would corrupt it.
+  """
+  for node in new_nodes:
+    _InsertNodeAt(node, target, after=False)
+
+
+def InsertNodesAfter(new_nodes, target):
+  """Insert new_nodes after the given target location in the tree.
+
+  Arguments:
+    new_nodes: a sequence of new nodes to insert (the nodes should not be in the
+      tree).
+    target: the target node after which the new node node will be inserted.
+
+  Raises:
+    RuntimeError: if the tree is corrupted, or the insertion would corrupt it.
+  """
+  for node in reversed(new_nodes):
+    _InsertNodeAt(node, target, after=True)
+
+
+def _InsertNodeAt(new_node, target, after=False):
+  """Underlying implementation for node insertion.
+
+  Arguments:
+    new_node: a new node to insert (this node should not be in the tree).
+    target: the target node.
+    after: if True, new_node is inserted after target. Otherwise, it's inserted
+      before target.
+
+  Returns:
+    nothing
+
+  Raises:
+    RuntimeError: if the tree is corrupted, or the insertion would corrupt it.
+  """
+
+  # Protect against attempts to insert nodes which already belong to some tree.
+  if new_node.parent is not None:
+    raise RuntimeError('inserting node which already has a parent',
+                       (new_node, new_node.parent))
+
+  # The code here is based on pytree.Base.next_sibling
+  parent_of_target = target.parent
+  if parent_of_target is None:
+    raise RuntimeError('expected target node to have a parent', (target,))
+
+  for i, child in enumerate(parent_of_target.children):
+    if child is target:
+      insertion_index = i + 1 if after else i
+      parent_of_target.insert_child(insertion_index, new_node)
+      return
+
+  raise RuntimeError('unable to find insertion point for target node',
+                     (target,))
+
+# The following constant and functions implement a simple custom annotation
+# mechanism for pytree nodes. We attach new attributes to nodes. Each attribute
+# is prefixed with _NODE_ANNOTATION_PREFIX. These annotations should only be
+# managed through GetNodeAnnotation and SetNodeAnnotation.
+_NODE_ANNOTATION_PREFIX = '_yapf_annotation_'
+
+
+def GetNodeAnnotation(node, annotation):
+  """Get annotation value from a node.
+
+  Arguments:
+    node: the node.
+    annotation: annotation name - a string.
+
+  Returns:
+    Value of the annotation in the given node. If the node doesn't have this
+    particular annotation name yet, returns None.
+  """
+  return getattr(node, _NODE_ANNOTATION_PREFIX + annotation, None)
+
+
+def SetNodeAnnotation(node, annotation, value):
+  """Set annotation value on a node.
+
+  Arguments:
+    node: the node.
+    annotation: annotation name - a string.
+    value: annotation value to set.
+  """
+  setattr(node, _NODE_ANNOTATION_PREFIX + annotation, value)
+
+
+def DumpNodeToString(node):
+  """Dump a string representation of the given node. For debugging.
+
+  Arguments:
+    node: the node.
+
+  Returns:
+    The string representation.
+  """
+  if isinstance(node, pytree.Leaf):
+    fmt = '{name}({value}) [lineno={lineno}, column={column}, prefix={prefix}]'
+    return fmt.format(name=NodeName(node),
+                      value=repr(node),
+                      lineno=node.lineno,
+                      column=node.column,
+                      prefix=repr(node.prefix))
+  else:
+    fmt = '{node} [{len} children] [child_indent="{indent}"]'
+    return fmt.format(node=NodeName(node),
+                      len=len(node.children),
+                      indent=GetNodeAnnotation(node, Annotation.CHILD_INDENT))
+
+
+def IsCommentStatement(node):
+  return (NodeName(node) == 'simple_stmt' and
+          NodeName(node.children[0]) == 'COMMENT')
diff --git a/yapf/yapflib/pytree_visitor.py b/yapf/yapflib/pytree_visitor.py
new file mode 100644
index 0000000..49da056
--- /dev/null
+++ b/yapf/yapflib/pytree_visitor.py
@@ -0,0 +1,135 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Generic visitor pattern for pytrees.
+
+The lib2to3 parser produces a "pytree" - syntax tree consisting of Node
+and Leaf types. This module implements a visitor pattern for such trees.
+
+It also exports a basic "dumping" visitor that dumps a textual representation of
+a pytree into a stream.
+
+  PyTreeVisitor: a generic visitor pattern fo pytrees.
+  PyTreeDumper: a configurable "dumper" for displaying pytrees.
+  DumpPyTree(): a convenience function to dump a pytree.
+"""
+
+import sys
+
+from lib2to3 import pytree
+
+from yapf.yapflib import pytree_utils
+
+
+class PyTreeVisitor(object):
+  """Visitor pattern for pytree trees.
+
+  Methods named Visit_XXX will be invoked when a node with type XXX is
+  encountered in the tree. The type is either a token type (for Leaf nodes) or
+  grammar symbols (for Node nodes). The return value of Visit_XXX methods is
+  ignored by the visitor.
+
+  Visitors can modify node contents but must not change the tree structure
+  (e.g. add/remove children and move nodes around).
+
+  This is a very common visitor pattern in Python code; it's also used in the
+  Python standard library ast module for providing AST visitors.
+
+  Note: this makes names that aren't style conformant, so such visitor methods
+  need to be marked with # pylint: disable=invalid-name We don't have a choice
+  here, because lib2to3 nodes have under_separated names.
+
+  For more complex behavior, the visit, DefaultNodeVisit and DefaultLeafVisit
+  methods can be overridden. Don't forget to invoke DefaultNodeVisit for nodes
+  that may have children - otherwise the children will not be visited.
+  """
+
+  def Visit(self, node):
+    """Visit a node."""
+    method = 'Visit_{0}'.format(pytree_utils.NodeName(node))
+    if hasattr(self, method):
+      # Found a specific visitor for this node
+      getattr(self, method)(node)
+    else:
+      if isinstance(node, pytree.Leaf):
+        self.DefaultLeafVisit(node)
+      else:
+        self.DefaultNodeVisit(node)
+
+  def DefaultNodeVisit(self, node):
+    """Default visitor for Node: visits the node's children depth-first.
+
+    This method is invoked when no specific visitor for the node is defined.
+
+    Arguments:
+      node: the node to visit
+    """
+    for child in node.children:
+      self.Visit(child)
+
+  def DefaultLeafVisit(self, leaf):
+    """Default visitor for Leaf: no-op.
+
+    This method is invoked when no specific visitor for the leaf is defined.
+
+    Arguments:
+      leaf: the leaf to visit
+    """
+    pass
+
+
+def DumpPyTree(tree, target_stream=sys.stdout):
+  """Convenience function for dumping a given pytree.
+
+  This function presents a very minimal interface. For more configurability (for
+  example, controlling how specific node types are displayed), use PyTreeDumper
+  directly.
+
+  Arguments:
+    tree: the tree to dump.
+    target_stream: the stream to dump the tree to. A file-like object. By
+      default will dump into stdout.
+  """
+  dumper = PyTreeDumper(target_stream)
+  dumper.Visit(tree)
+
+
+class PyTreeDumper(PyTreeVisitor):
+  """Visitor that dumps the tree to a stream.
+
+  Implements the PyTreeVisitor interface.
+  """
+
+  def __init__(self, target_stream=sys.stdout):
+    """Create a tree dumper.
+
+    Arguments:
+      target_stream: the stream to dump the tree to. A file-like object. By
+        default will dump into stdout.
+    """
+    self._target_stream = target_stream
+    self._current_indent = 0
+
+  def _DumpString(self, s):
+    self._target_stream.write('{0}{1}\n'.format(' ' * self._current_indent, s))
+
+  def DefaultNodeVisit(self, node):
+    # Dump information about the current node, and then use the generic
+    # DefaultNodeVisit visitor to dump each of its children.
+    self._DumpString(pytree_utils.DumpNodeToString(node))
+    self._current_indent += 2
+    super(PyTreeDumper, self).DefaultNodeVisit(node)
+    self._current_indent -= 2
+
+  def DefaultLeafVisit(self, leaf):
+    self._DumpString(pytree_utils.DumpNodeToString(leaf))
diff --git a/yapf/yapflib/reformatter.py b/yapf/yapflib/reformatter.py
new file mode 100644
index 0000000..7cecbdf
--- /dev/null
+++ b/yapf/yapflib/reformatter.py
@@ -0,0 +1,451 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Decide what the format for the code should be.
+
+The `unwrapped_line.UnwrappedLine`s are now ready to be formatted.
+UnwrappedLines that can be merged together are. The best formatting is returned
+as a string.
+
+  Reformat(): the main function exported by this module.
+"""
+
+import collections
+import heapq
+import re
+
+from yapf.yapflib import format_decision_state
+from yapf.yapflib import line_joiner
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import style
+from yapf.yapflib import verifier
+
+
+def Reformat(uwlines):
+  """Reformat the unwrapped lines.
+
+  Arguments:
+    uwlines: (list of unwrapped_line.UnwrappedLine) Lines we want to format.
+
+  Returns:
+    A string representing the reformatted code.
+  """
+  final_lines = []
+  prev_last_token = None  # Last token of the previous line.
+
+  for uwline in _SingleOrMergedLines(uwlines):
+    first_token = uwline.first
+    _FormatFirstToken(first_token, uwline.depth, prev_last_token)
+
+    indent_amt = style.INDENT_WIDTH * uwline.depth
+    state = format_decision_state.FormatDecisionState(uwline, indent_amt)
+    if _LineContainsI18n(uwline):
+      _EmitLineUnformatted(state)
+    elif _CanPlaceOnSingleLine(uwline):
+      # The unwrapped line fits on one line.
+      while state.next_token:
+        state.AddTokenToState(newline=False, dry_run=False)
+    else:
+      _AnalyzeSolutionSpace(state, dry_run=False)
+
+    final_lines.append(uwline)
+    prev_last_token = uwline.last
+
+  formatted_code = []
+  for line in final_lines:
+    formatted_line = []
+    for token in line.tokens:
+      if token.name in pytree_utils.NONSEMANTIC_TOKENS:
+        continue
+      formatted_line.append(token.whitespace_prefix)
+      formatted_line.append(token.value)
+    formatted_code.append(''.join(formatted_line))
+    verifier.VerifyCode(formatted_code[-1])
+
+  return ''.join(formatted_code) + '\n'
+
+
+def _EmitLineUnformatted(state):
+  """Emit the line without formatting.
+
+  The line contains code that if reformatted would break a non-syntactic
+  convention. E.g., i18n comments and function calls are tightly bound by
+  convention. Instead, we calculate when / if a newline should occur and honor
+  that. But otherwise the code emitted will be the same as the original code.
+
+  Arguments:
+    state: (format_decision_state.FormatDecisionState) The format decision
+      state.
+  """
+  prev_lineno = None
+  while state.next_token:
+    newline = (
+        prev_lineno is not None and
+        state.next_token.lineno > state.next_token.previous_token.lineno
+    )
+    prev_lineno = state.next_token.lineno
+    state.AddTokenToState(newline=newline, dry_run=False)
+
+
+def _LineContainsI18n(uwline):
+  """Return true if there are i18n comments or function calls in the line.
+
+  I18n comments and pseudo-function calls are closely related. They cannot
+  be moved apart without breaking i18n.
+
+  Arguments:
+    uwline: (unwrapped_line.UnwrappedLine) The line currently being formatted.
+
+  Returns:
+    True if the line contains i18n comments or function calls. False otherwise.
+  """
+  if style.I18N_COMMENT and any(re.search(style.I18N_COMMENT, token.value)
+                                for token in uwline.tokens):
+    # Contains an i18n comment.
+    return True
+
+  if style.I18N_FUNCTION_CALL:
+    length = len(uwline.tokens)
+    index = 0
+    while index < length - 1:
+      if (uwline.tokens[index + 1].value == '(' and
+          uwline.tokens[index].value in style.I18N_FUNCTION_CALL):
+        return True
+      index += 1
+
+  return False
+
+
+def _CanPlaceOnSingleLine(uwline):
+  """Determine if the unwrapped line can go on a single line.
+
+  Arguments:
+    uwline: (unwrapped_line.UnwrappedLine) The line currently being formatted.
+
+  Returns:
+    True if the line can or should be added to a single line. False otherwise.
+  """
+  indent_amt = style.INDENT_WIDTH * uwline.depth
+  return (uwline.last.total_length + indent_amt <= style.COLUMN_LIMIT and
+          not any(token.is_comment for token in uwline.tokens[:-1]))
+
+
+class _StateNode(object):
+  """An edge in the solution space from 'previous.state' to 'state'.
+
+  Attributes:
+    state: (format_decision_state.FormatDecisionState) The format decision state
+      for this node.
+    newline: If True, then on the edge from 'previous.state' to 'state' a
+      newline is inserted.
+    previous: (_StateNode) The previous state node in the graph.
+  """
+
+  # TODO(morbo): Add a '__cmp__' method.
+
+  def __init__(self, state, newline, previous):
+    self.state = state.Clone()
+    self.newline = newline
+    self.previous = previous
+
+  def __repr__(self):
+    return 'StateNode(state=[\n{0}\n], newline={1})'.format(self.state,
+                                                            self.newline)
+
+# A tuple of (penalty, count) that is used to prioritize the BFS. In case of
+# equal penalties, we prefer states that were inserted first. During state
+# generation, we make sure that we insert states first that break the line as
+# late as possible.
+_OrderedPenalty = collections.namedtuple('OrderedPenalty', ['penalty', 'count'])
+
+# An item in the prioritized BFS search queue. The 'StateNode's 'state' has
+# the given '_OrderedPenalty'.
+_QueueItem = collections.namedtuple('QueueItem', ['ordered_penalty',
+                                                  'state_node'])
+
+
+def _AnalyzeSolutionSpace(initial_state, dry_run=False):
+  """Analyze the entire solution space starting from initial_state.
+
+  This implements a variant of Dijkstra's algorithm on the graph that spans
+  the solution space (LineStates are the nodes). The algorithm tries to find
+  the shortest path (the one with the lowest penalty) from 'initial_state' to
+  the state where all tokens are placed.
+
+  Arguments:
+    initial_state: (format_decision_state.FormatDecisionState) The initial state
+      to start the search from.
+    dry_run: (bool) Don't commit changes if True.
+  """
+  count = 0
+  seen = set()
+  p_queue = []
+
+  # Insert start element.
+  node = _StateNode(initial_state, False, None)
+  heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(0, count), node))
+
+  count += 1
+  prev_penalty = 0
+  while p_queue:
+    item = p_queue[0]
+    penalty = item.ordered_penalty.penalty
+    node = item.state_node
+    if not node.state.next_token:
+      break
+    heapq.heappop(p_queue)
+
+    if count > 10000:
+      node.state.ignore_stack_for_comparison = True
+
+    if node.state in seen:
+      continue
+
+    assert penalty >= prev_penalty
+    prev_penalty = penalty
+
+    seen.add(node.state)
+
+    # FIXME(morbo): Add a 'decision' element?
+
+    count = _AddNextStateToQueue(penalty, node, False, count, p_queue)
+    count = _AddNextStateToQueue(penalty, node, True, count, p_queue)
+
+  if not p_queue:
+    # We weren't able to find a solution. Do nothing.
+    return
+
+  if not dry_run:
+    _ReconstructPath(initial_state, heapq.heappop(p_queue).state_node)
+
+
+def _AddNextStateToQueue(penalty, previous_node, newline, count, p_queue):
+  """Add the following state to the analysis queue.
+
+  Assume the current state is 'previous_node' and has been reached with a
+  penalty of 'penalty'. Insert a line break if 'newline' is True.
+
+  Arguments:
+    penalty: (int) The penalty associated with the path up to this point.
+    previous_node: (_StateNode) The last _StateNode inserted into the priority
+      queue.
+    newline: (bool) Add a newline if True.
+    count: (int) The number of elements in the queue.
+    p_queue: (heapq) The priority queue representing the solution space.
+
+  Returns:
+    The updated number of elements in the queue.
+  """
+  if newline and not previous_node.state.CanSplit():
+    # Don't add a newline if the token cannot be split.
+    return count
+  if not newline and previous_node.state.MustSplit():
+    # Don't add a token we must split but where we aren't splitting.
+    return count
+
+  if previous_node.state.next_token.value in pytree_utils.CLOSING_BRACKETS:
+    if _MatchingParenSplitDecision(previous_node) != newline:
+      penalty += style.SPLIT_PENALTY_MATCHING_BRACKET
+
+  node = _StateNode(previous_node.state, newline, previous_node)
+  penalty += node.state.AddTokenToState(newline=newline, dry_run=True)
+  heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(penalty, count), node))
+  return count + 1
+
+
+def _ReconstructPath(initial_state, current):
+  """Reconstruct the path through the queue with lowest penalty.
+
+  Arguments:
+    initial_state: (format_decision_state.FormatDecisionState) The initial state
+      to start the search from.
+    current: (_StateNode) The node in the decision graph that is the end point
+      of the path with the least penalty.
+  """
+  path = collections.deque()
+
+  while current.previous:
+    path.appendleft(current)
+    current = current.previous
+
+  for node in path:
+    initial_state.AddTokenToState(newline=node.newline, dry_run=False)
+
+
+def _MatchingParenSplitDecision(current):
+  """Returns the splitting decision of the matching token.
+
+  Arguments:
+    current: (_StateNode) The node in the decision graph that is the end point
+      of the path with the least penalty.
+
+  Returns:
+    True if the matching paren split after it, False otherwise.
+  """
+  # FIXME(morbo): This is not ideal, because it backtracks through code.
+  # In the general case, it shouldn't be too bad, but it is technically
+  # O(n^2) behavior, which is never good.
+  matching_bracket = current.state.next_token.matching_bracket
+  newline = current.newline
+  while current.previous:
+    if current.state.next_token.previous_token == matching_bracket:
+      break
+    newline = current.newline
+    current = current.previous
+  return newline or current.state.next_token.is_comment
+
+
+def _FormatFirstToken(first_token, indent_depth, prev_last_token):
+  """Format the first token in the unwrapped line.
+
+  Add a newline and the required indent before the first token of the unwrapped
+  line.
+
+  Arguments:
+    first_token: (format_token.FormatToken) The first token in the unwrapped
+      line.
+    indent_depth: (int) The line's indentation depth.
+    prev_last_token: (format_token.FormatToken) The last token of the previous
+      unwrapped line.
+  """
+  first_token.AddWhitespacePrefix(_CalculateNumberOfNewlines(first_token,
+                                                             indent_depth,
+                                                             prev_last_token),
+                                  indent_level=indent_depth)
+
+
+NO_BLANK_LINES = 1
+ONE_BLANK_LINE = 2
+TWO_BLANK_LINES = 3
+
+
+def _CalculateNumberOfNewlines(first_token, indent_depth, prev_last_token):
+  """Calculate the number of newlines we need to add.
+
+  Arguments:
+    first_token: (format_token.FormatToken) The first token in the unwrapped
+      line.
+    indent_depth: (int) The line's indentation depth.
+    prev_last_token: (format_token.FormatToken) The last token of the previous
+      unwrapped line.
+
+  Returns:
+    The number of newlines needed before the first token.
+  """
+  # TODO(morbo): Special handling for imports.
+  # TODO(morbo): Create a knob that can tune these.
+  if prev_last_token is None:
+    # The first line in the file. Don't add blank lines.
+    # FIXME(morbo): Is this correct?
+    if first_token.newlines is not None:
+      pytree_utils.SetNodeAnnotation(first_token.GetPytreeNode(),
+                                     pytree_utils.Annotation.NEWLINES, None)
+    return 0
+
+  if first_token.is_docstring:
+    # The docstring shouldn't have a newline before it.
+    # TODO(morbo): Add a knob to adjust this.
+    return NO_BLANK_LINES
+
+  if prev_last_token.is_docstring:
+    if not indent_depth and first_token.value in {'class', 'def'}:
+      # Separate a class or function from the module-level docstring with two
+      # blank lines.
+      return TWO_BLANK_LINES
+    if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token,
+                                       prev_last_token):
+      return NO_BLANK_LINES
+    else:
+      return ONE_BLANK_LINE
+
+  if first_token.value in {'class', 'def'}:
+    # TODO(morbo): This can go once the blank line calculator is more
+    # sophisticated.
+    if not indent_depth:
+      # This is a top-level class or function.
+      is_inline_comment = prev_last_token.whitespace_prefix.count('\n') == 0
+      if prev_last_token.is_comment and not is_inline_comment:
+        # This token follows a non-inline comment.
+        if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token,
+                                           prev_last_token):
+          # Assume that the comment is "attached" to the current line.
+          # Therefore, we want two blank lines before the comment.
+          prev_last_token.AdjustNewlinesBefore(TWO_BLANK_LINES)
+          if first_token.newlines is not None:
+            pytree_utils.SetNodeAnnotation(first_token.GetPytreeNode(),
+                                           pytree_utils.Annotation.NEWLINES,
+                                           None)
+          return NO_BLANK_LINES
+
+  # Calculate how many newlines were between the original lines. We want to
+  # retain that formatting if it doesn't violate one of the style guide rules.
+  if first_token.is_comment:
+    first_token_lineno = first_token.lineno - first_token.value.count('\n')
+  else:
+    first_token_lineno = first_token.lineno
+
+  if first_token_lineno - prev_last_token.lineno > 1:
+    return ONE_BLANK_LINE
+  else:
+    return NO_BLANK_LINES
+
+
+def _SingleOrMergedLines(uwlines):
+  """Generate the lines we want to format.
+
+  Arguments:
+    uwlines: (list of unwrapped_line.UnwrappedLine) Lines we want to format.
+
+  Yields:
+    Either a single line, if the current line cannot be merged with the
+    succeeding line, or the next two lines merged into one line.
+  """
+  index = 0
+  while index < len(uwlines):
+    # TODO(morbo): This splice is potentially very slow. Come up with a more
+    # performance-friendly way of determining if two lines can be merged.
+    if line_joiner.CanMergeMultipleLines(uwlines[index:]):
+      for token in uwlines[index + 1].tokens:
+        uwlines[index].AppendToken(token)
+      yield uwlines[index]
+      index += 2
+    else:
+      yield uwlines[index]
+      index += 1
+
+
+def _NoBlankLinesBeforeCurrentToken(text, cur_token, prev_token):
+  """Determine if there are no blank lines before the current token.
+
+  The previous token is a docstring or comment. The prev_token_lineno is the
+  start of the text of that token. Counting the number of newlines in its text
+  gives us the extent and thus where the line number of the end of the
+  docstring or comment. After that, we just compare it to the current token's
+  line number to see if there are blank lines between them.
+
+  Arguments:
+    text: (unicode) The text of the docstring or comment before the current
+      token.
+    cur_token: (format_token.FormatToken) The current token in the unwrapped
+      line.
+    prev_token: (format_token.FormatToken) The previous token in the unwrapped
+      line.
+
+  Returns:
+    True if there is no blank line before the current token.
+  """
+  cur_token_lineno = cur_token.lineno
+  if cur_token.is_comment:
+    cur_token_lineno -= cur_token.value.count('\n')
+  num_newlines = text.count('\n') if not prev_token.is_comment else 0
+  return prev_token.lineno + num_newlines == cur_token_lineno - 1
diff --git a/yapf/yapflib/split_penalty.py b/yapf/yapflib/split_penalty.py
new file mode 100644
index 0000000..004b05e
--- /dev/null
+++ b/yapf/yapflib/split_penalty.py
@@ -0,0 +1,268 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Computation of split penalties before/between tokens."""
+
+from lib2to3 import pytree
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+
+UNBREAKABLE = 1000 * 1000
+STRONGLY_CONNECTED = 1000
+ARITHMETIC_EXPRESSION = 42
+
+# TODO(morbo): Document the annotations in a centralized place. E.g., the
+# README file.
+
+
+def ComputeSplitPenalties(tree):
+  """Compute split penalties on tokens in the given parse tree.
+
+  Arguments:
+    tree: the top-level pytree node to annotate with penalties.
+  """
+  _TreePenaltyAssigner().Visit(tree)
+
+
+class _TreePenaltyAssigner(pytree_visitor.PyTreeVisitor):
+  """Assigns split penalties to tokens, based on parse tree structure.
+
+  Split penalties are attached as annotations to tokens.
+  """
+
+  def Visit_classdef(self, node):  # pylint: disable=invalid-name
+    # classdef ::= 'class' NAME ['(' [arglist] ')'] ':' suite
+    #
+    # NAME
+    self._SetUnbreakable(node.children[1])
+    if len(node.children) > 4:
+      # opening '('
+      self._SetUnbreakable(node.children[2])
+    # ':'
+    self._SetUnbreakable(node.children[-2])
+    self.DefaultNodeVisit(node)
+
+  def Visit_funcdef(self, node):  # pylint: disable=invalid-name
+    # funcdef ::= 'def' NAME parameters ['->' test] ':' suite
+    #
+    # Can't break before the function name and before the colon. The parameters
+    # are handled by child iteration.
+    colon_idx = 1
+    while pytree_utils.NodeName(node.children[colon_idx]) == 'simple_stmt':
+      colon_idx += 1
+    self._SetUnbreakable(node.children[colon_idx])
+    while colon_idx < len(node.children):
+      if (isinstance(node.children[colon_idx], pytree.Leaf) and
+          node.children[colon_idx].value == ':'):
+        break
+      colon_idx += 1
+    self._SetUnbreakable(node.children[colon_idx])
+    self.DefaultNodeVisit(node)
+
+  def Visit_lambdef(self, node):  # pylint: disable=invalid-name
+    # lambdef ::= 'lambda' [varargslist] ':' test
+    # Loop over the lambda up to and including the colon.
+    lambda_has_arglist = pytree_utils.NodeName(node.children[1]) != 'COLON'
+    self._SetUnbreakableOnChildren(node,
+                                   num_children=3 if lambda_has_arglist else 2)
+
+  def Visit_parameters(self, node):  # pylint: disable=invalid-name
+    # parameters ::= '(' [typedargslist] ')'
+    self.DefaultNodeVisit(node)
+
+    # Can't break before the opening paren of a parameter list.
+    self._SetUnbreakable(node.children[0])
+    if len(node.children) == 2:
+      # Don't split an empty argument list if at all possible.
+      self._SetStronglyConnected(node.children[1])
+
+  def Visit_dotted_name(self, node):  # pylint: disable=invalid-name
+    # dotted_name ::= NAME ('.' NAME)*
+    self._SetUnbreakableOnChildren(node, num_children=len(node.children))
+
+  def Visit_dictsetmaker(self, node):  # pylint: disable=invalid-name
+    # dictsetmaker ::= ( (test ':' test
+    #                      (comp_for | (',' test ':' test)* [','])) |
+    #                    (test (comp_for | (',' test)* [','])) )
+    prev_child = None
+    for child in node.children:
+      self.Visit(child)
+      if pytree_utils.NodeName(child) == 'COLON':
+        # This is a key to a dictionary. We don't want to split the key if at
+        # all possible.
+        self._SetStronglyConnected(prev_child, child)
+      prev_child = child
+
+  def Visit_comparison(self, node):  # pylint: disable=invalid-name
+    # comparison ::= expr (comp_op expr)*
+    self.DefaultNodeVisit(node)
+    self._SetArithmeticExpression(node)
+
+  def Visit_arith_expr(self, node):  # pylint: disable=invalid-name
+    # arith_expr ::= term (('+'|'-') term)*
+    self.DefaultNodeVisit(node)
+    self._SetArithmeticExpression(node)
+
+  def Visit_term(self, node):  # pylint: disable=invalid-name
+    # term ::= factor (('*'|'/'|'%'|'//') factor)*
+    self.DefaultNodeVisit(node)
+    self._SetArithmeticExpression(node)
+
+  def Visit_trailer(self, node):  # pylint: disable=invalid-name
+    # trailer ::= '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+    self.DefaultNodeVisit(node)
+    if node.children[0].value == '.':
+      self._SetStronglyConnected(node.children[0], node.children[-1])
+    elif node.children[0].value == '[':
+      self._SetStronglyConnected(node.children[-1])
+
+  def Visit_power(self, node):  # pylint: disable=invalid-name,missing-docstring
+    # power: atom trailer* ['**' factor]
+    self.DefaultNodeVisit(node)
+
+    # See if this node is surrounded by parentheses. If it is, then we can
+    # relax some of the formatting restrictions.
+    surrounded_by_parens = (
+        node.parent and pytree_utils.NodeName(node.parent) == 'atom' and
+        isinstance(node.parent.children[0], pytree.Leaf) and
+        node.parent.children[0].value == '(' and
+        isinstance(node.parent.children[-1], pytree.Leaf) and
+        node.parent.children[-1].value == ')')
+
+    # When atom is followed by a trailer, we can not break between them.
+    # E.g. arr[idx] - no break allowed between 'arr' and '['.
+    if (len(node.children) > 1 and
+        pytree_utils.NodeName(node.children[1]) == 'trailer'):
+      # children[1] itself is a whole trailer: we don't want to
+      # mark all of it as unbreakable, only its first token: (, [ or .
+      self._SetUnbreakable(node.children[1].children[0])
+
+      # A special case when there are more trailers in the sequence. Given:
+      #   atom tr1 tr2
+      # The last token of tr1 and the first token of tr2 comprise an unbreakable
+      # region. For example: foo.bar.baz(1)
+      # We can't put breaks between either of the '.' or the '(' and the names
+      # *preceding* them.
+      prev_trailer_idx = 1
+      while prev_trailer_idx < len(node.children) - 1:
+        cur_trailer_idx = prev_trailer_idx + 1
+        cur_trailer = node.children[cur_trailer_idx]
+        if pytree_utils.NodeName(cur_trailer) == 'trailer':
+          # Now we know we have two trailers one after the other
+          prev_trailer = node.children[prev_trailer_idx]
+          if prev_trailer.children[-1].value != ')':
+            # Set the previous node unbreakable if it's not a function call:
+            #   atom tr1() tr2
+            # It may be necessary (though undesirable) to split up a previous
+            # function call's parentheses to the next line.
+            self._SetUnbreakable(prev_trailer.children[-1])
+          if not surrounded_by_parens:
+            # If this is surrounded by parentheses, we can allow the '.' to be
+            # on the next line. This is for "builder" type calling chains.
+            self._SetUnbreakable(cur_trailer.children[0])
+          prev_trailer_idx = cur_trailer_idx
+        else:
+          break
+
+    # We don't want to split before the last ')' of a function call. This also
+    # takes care of the special case of:
+    #   atom tr1 tr2 ... trn
+    # where the 'tr#' are trailers that may end in a ')'.
+    for trailer in node.children[1:]:
+      if pytree_utils.NodeName(trailer) != 'trailer':
+        break
+      if trailer.children[0].value == '(' and len(trailer.children) > 2:
+        # If the trailer's children are '()', then don't set the ')' as
+        # unbreakable. It's sometimes necessary, though undesirable, to split
+        # the two.
+        self._SetUnbreakable(trailer.children[-1])
+
+  def Visit_subscript(self, node):  # pylint: disable=invalid-name
+    # subscript ::= test | [test] ':' [test] [sliceop]
+    self._SetStronglyConnected(*node.children)
+    self.DefaultNodeVisit(node)
+
+  def Visit_comp_for(self, node):  # pylint: disable=invalid-name
+    # comp_for ::= 'for' exprlist 'in' testlist_safe [comp_iter]
+    self._SetStronglyConnected(*node.children[1:])
+    self.DefaultNodeVisit(node)
+
+  def Visit_comp_if(self, node):  # pylint: disable=invalid-name
+    # comp_if ::= 'if' old_test [comp_iter]
+    pytree_utils.SetNodeAnnotation(node.children[0],
+                                   pytree_utils.Annotation.SPLIT_PENALTY, None)
+    self._SetStronglyConnected(*node.children[1:])
+    self.DefaultNodeVisit(node)
+
+  ############################################################################
+  # Helper methods that set the annotations.
+
+  def _SetUnbreakable(self, node):
+    """Set an UNBREAKABLE penalty annotation for the given node."""
+    self._RecAnnotate(node, pytree_utils.Annotation.SPLIT_PENALTY, UNBREAKABLE)
+
+  def _SetStronglyConnected(self, *nodes):
+    """Set a STRONGLY_CONNECTED penalty annotation for the given nodes."""
+    for node in nodes:
+      self._RecAnnotate(node, pytree_utils.Annotation.SPLIT_PENALTY,
+                        STRONGLY_CONNECTED)
+
+  def _SetUnbreakableOnChildren(self, node, num_children):
+    """Set an UNBREAKABLE penalty annotation on children of node."""
+    for child in node.children:
+      self.Visit(child)
+    for i in xrange(1, num_children):
+      self._SetUnbreakable(node.children[i])
+
+  def _SetArithmeticExpression(self, node):
+    """Set an ARITHMETIC_EXPRESSION penalty annotation children nodes."""
+
+    def FirstChildNode(node):
+      if isinstance(node, pytree.Leaf):
+        return node
+      return FirstChildNode(node.children[0])
+
+    def RecArithmeticExpression(node, first_child_leaf):
+      if node is first_child_leaf:
+        return
+
+      if isinstance(node, pytree.Leaf):
+        if pytree_utils.GetNodeAnnotation(
+            node,
+            pytree_utils.Annotation.SPLIT_PENALTY) < ARITHMETIC_EXPRESSION:
+          pytree_utils.SetNodeAnnotation(
+              node,
+              pytree_utils.Annotation.SPLIT_PENALTY, ARITHMETIC_EXPRESSION)
+      else:
+        for child in node.children:
+          RecArithmeticExpression(child, first_child_leaf)
+
+    RecArithmeticExpression(node, FirstChildNode(node))
+
+  def _RecAnnotate(self, tree, annotate_name, annotate_value):
+    """Recursively set the given annotation on all leafs of the subtree.
+
+    Takes care to only increase the penalty. If the node already has a higher
+    or equal penalty associated with it, this is a no-op.
+
+    Args:
+      tree: subtree to annotate
+      annotate_name: name of the annotation to set
+      annotate_value: value of the annotation to set
+    """
+    for child in tree.children:
+      self._RecAnnotate(child, annotate_name, annotate_value)
+    if isinstance(tree, pytree.Leaf):
+      if pytree_utils.GetNodeAnnotation(tree, annotate_name) < annotate_value:
+        pytree_utils.SetNodeAnnotation(tree, annotate_name, annotate_value)
diff --git a/yapf/yapflib/style.py b/yapf/yapflib/style.py
new file mode 100644
index 0000000..94a5cf6
--- /dev/null
+++ b/yapf/yapflib/style.py
@@ -0,0 +1,69 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Python format style guidelines."""
+
+# The column limit.
+COLUMN_LIMIT = 80
+
+# Indent width for line continuations.
+CONTINUATION_INDENT_WIDTH = 4
+
+# The regex for an i18n comment. The presence of this comment stops reformatting
+# of that line, because the comments are required to be next to the string they
+# translate.
+I18N_COMMENT = r'#\..*'
+
+# The i18n function call names. The presence of this function stops
+# reformattting on that line, because the string it has cannot be moved away
+# from the i18n comment.
+I18N_FUNCTION_CALL = ('N_', '_')
+
+# The number of columns to use for indentation.
+INDENT_WIDTH = 4
+
+# The number of spaces required before a trailing comment.
+SPACES_BEFORE_COMMENT = 2
+
+# Set to True to prefer splitting before 'and' or 'or' rather than after.
+SPLIT_BEFORE_LOGICAL_OPERATOR = False
+
+# Split named assignments onto individual lines.
+SPLIT_BEFORE_NAMED_ASSIGNS = True
+
+# The penalty for splitting the line after a unary operator.
+SPLIT_PENALTY_AFTER_UNARY_OPERATOR = 100
+
+# The penalty for characters over the column limit.
+SPLIT_PENALTY_EXCESS_CHARACTER = 200
+
+# The penalty of splitting the line around the 'and' and 'or' operators.
+SPLIT_PENALTY_LOGICAL_OPERATOR = 30
+
+# The penalty for not matching the splitting decision for the matching bracket
+# tokens. For instance, if there is a newline after the opening bracket, we
+# would tend to expect one before the closing bracket, and vice versa.
+SPLIT_PENALTY_MATCHING_BRACKET = 50
+
+# The penalty for splitting right after the opening bracket.
+SPLIT_PENALTY_AFTER_OPENING_BRACKET = 30
+
+# The penalty incurred by adding a line split to the unwrapped line. The more
+# line splits added the higher the penalty.
+SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT = 30
+
+# The number of columns used for tab stops.
+TAB_WIDTH = 8
+
+# Use tabs in the resulting file.
+USE_TAB = False
diff --git a/yapf/yapflib/subtype_assigner.py b/yapf/yapflib/subtype_assigner.py
new file mode 100644
index 0000000..35b70b5
--- /dev/null
+++ b/yapf/yapflib/subtype_assigner.py
@@ -0,0 +1,245 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Subtype assigner for lib2to3 trees.
+
+This module assigns extra type information to the lib2to3 trees. This
+information is more specific than whether something is an operator or an
+identifier. For instance, it can specify if a node in the tree is part of a
+subscript.
+
+  AssignSubtypes(): the main function exported by this module.
+
+Annotations:
+  subtype: The subtype of a pytree token. See 'format_token' module for a list
+      of subtypes.
+"""
+
+from lib2to3 import pytree
+
+from yapf.yapflib import format_token
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+
+
+def AssignSubtypes(tree):
+  """Run the subtype assigner visitor over the tree, modifying it in place.
+
+  Arguments:
+    tree: the top-level pytree node to annotate with subtypes.
+  """
+  subtype_assigner = _SubtypeAssigner()
+  subtype_assigner.Visit(tree)
+
+# Map tokens in argument lists to their respective subtype.
+_ARGLIST_TOKEN_TO_SUBTYPE = {
+    '=': format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN,
+    '*': format_token.Subtype.VARARGS_STAR,
+    '**': format_token.Subtype.KWARGS_STAR_STAR,
+}
+
+
+class _SubtypeAssigner(pytree_visitor.PyTreeVisitor):
+  """_SubtypeAssigner - see file-level docstring for detailed description.
+
+  The subtype is added as an annotation to the pytree token.
+  """
+
+  def Visit_dictsetmaker(self, node):  # pylint: disable=invalid-name
+    # dictsetmaker ::= (test ':' test (comp_for |
+    #                                   (',' test ':' test)* [','])) |
+    #                  (test (comp_for | (',' test)* [',']))
+    dict_maker = (
+        len(node.children) > 1 and isinstance(node.children[1], pytree.Leaf) and
+        node.children[1].value == ':'
+    )
+    last_was_comma = False
+    for child in node.children:
+      self.Visit(child)
+      if pytree_utils.NodeName(child) == 'comp_for':
+        self._SetFirstLeafTokenSubtype(child,
+                                       format_token.Subtype.DICT_SET_GENERATOR)
+      else:
+        if dict_maker and last_was_comma:
+          self._SetFirstLeafTokenSubtype(child,
+                                         format_token.Subtype.DICTIONARY_KEY)
+        last_was_comma = isinstance(child, pytree.Leaf) and child.value == ','
+
+  def Visit_expr_stmt(self, node):  # pylint: disable=invalid-name
+    # expr_stmt ::= testlist_star_expr (augassign (yield_expr|testlist)
+    #               | ('=' (yield_expr|testlist_star_expr))*)
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '=':
+        self._SetTokenSubtype(child, format_token.Subtype.ASSIGN_OPERATOR)
+
+  def Visit_or_test(self, node):  # pylint: disable=invalid-name
+    # or_test ::= and_test ('or' and_test)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == 'or':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_and_test(self, node):  # pylint: disable=invalid-name
+    # and_test ::= not_test ('and' not_test)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == 'and':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_not_test(self, node):  # pylint: disable=invalid-name
+    # not_test ::= 'not' not_test | comparison
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == 'not':
+        self._SetTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR)
+
+  def Visit_comparison(self, node):  # pylint: disable=invalid-name
+    # comparison ::= expr (comp_op expr)*
+    # comp_op ::= '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not in'|'is'|'is not'
+    for child in node.children:
+      self.Visit(child)
+      if (isinstance(child, pytree.Leaf) and child.value in {
+          '<', '>', '==', '>=', '<=', '<>', '!=', 'in', 'not in', 'is', 'is not'
+      }):
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_star_expr(self, node):  # pylint: disable=invalid-name
+    # star_expr ::= '*' expr
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '*':
+        self._SetTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR)
+
+  def Visit_expr(self, node):  # pylint: disable=invalid-name
+    # expr ::= xor_expr ('|' xor_expr)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '|':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_xor_expr(self, node):  # pylint: disable=invalid-name
+    # xor_expr ::= and_expr ('^' and_expr)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '^':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_and_expr(self, node):  # pylint: disable=invalid-name
+    # and_expr ::= shift_expr ('&' shift_expr)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '&':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_shift_expr(self, node):  # pylint: disable=invalid-name
+    # shift_expr ::= arith_expr (('<<'|'>>') arith_expr)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value in {'<<', '>>'}:
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_arith_expr(self, node):  # pylint: disable=invalid-name
+    # arith_expr ::= term (('+'|'-') term)*
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value in '+-':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_term(self, node):  # pylint: disable=invalid-name
+    # term ::= factor (('*'|'/'|'%'|'//') factor)*
+    for child in node.children:
+      self.Visit(child)
+      if (isinstance(child, pytree.Leaf) and
+          child.value in {'*', '/', '%', '//'}):
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_factor(self, node):  # pylint: disable=invalid-name
+    # factor ::= ('+'|'-'|'~') factor | power
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value in '+-~':
+        self._SetTokenSubtype(child, format_token.Subtype.UNARY_OPERATOR)
+
+  def Visit_power(self, node):  # pylint: disable=invalid-name
+    # power ::= atom trailer* ['**' factor]
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == '**':
+        self._SetTokenSubtype(child, format_token.Subtype.BINARY_OPERATOR)
+
+  def Visit_subscript(self, node):  # pylint: disable=invalid-name
+    # subscript ::= test | [test] ':' [test] [sliceop]
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == ':':
+        self._SetTokenSubtype(child, format_token.Subtype.SUBSCRIPT_COLON)
+
+  def Visit_sliceop(self, node):  # pylint: disable=invalid-name
+    # sliceop ::= ':' [test]
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf) and child.value == ':':
+        self._SetTokenSubtype(child, format_token.Subtype.SUBSCRIPT_COLON)
+
+  def Visit_argument(self, node):  # pylint: disable=invalid-name
+    # argument ::=
+    #     test [comp_for] | test '=' test
+    self._ProcessArgLists(node)
+
+  def Visit_arglist(self, node):  # pylint: disable=invalid-name
+    # arglist ::=
+    #     (argument ',')* (argument [',']
+    #                     | '*' test (',' argument)* [',' '**' test]
+    #                     | '**' test)
+    self._ProcessArgLists(node)
+
+  def Visit_typedargslist(self, node):  # pylint: disable=invalid-name
+    # typedargslist ::=
+    #     ((tfpdef ['=' test] ',')*
+    #          ('*' [tname] (',' tname ['=' test])* [',' '**' tname]
+    #           | '**' tname)
+    #     | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
+    self._ProcessArgLists(node)
+
+  def Visit_varargslist(self, node):  # pylint: disable=invalid-name
+    # varargslist ::=
+    #     ((vfpdef ['=' test] ',')*
+    #          ('*' [vname] (',' vname ['=' test])*  [',' '**' vname]
+    #           | '**' vname)
+    #      | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
+    self._ProcessArgLists(node)
+
+  def _ProcessArgLists(self, node):
+    """Common method for processing argument lists."""
+    for child in node.children:
+      self.Visit(child)
+      if isinstance(child, pytree.Leaf):
+        self._SetTokenSubtype(
+            child,
+            subtype=_ARGLIST_TOKEN_TO_SUBTYPE.get(child.value,
+                                                  format_token.Subtype.NONE))
+
+  def _SetTokenSubtype(self, node, subtype):
+    """Set the token's subtype only if it's not already set."""
+    if not pytree_utils.GetNodeAnnotation(node,
+                                          pytree_utils.Annotation.SUBTYPE):
+      pytree_utils.SetNodeAnnotation(node, pytree_utils.Annotation.SUBTYPE,
+                                     subtype)
+
+  def _SetFirstLeafTokenSubtype(self, node, subtype):
+    """Set the first leaf token's subtypes."""
+    if isinstance(node, pytree.Leaf):
+      self._SetTokenSubtype(node, subtype)
+      return
+    self._SetFirstLeafTokenSubtype(node.children[0], subtype)
diff --git a/yapf/yapflib/unwrapped_line.py b/yapf/yapflib/unwrapped_line.py
new file mode 100644
index 0000000..43a0ebc
--- /dev/null
+++ b/yapf/yapflib/unwrapped_line.py
@@ -0,0 +1,390 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""UnwrappedLine primitive for formatting.
+
+An unwrapped line is the containing data structure produced by the parser. It
+collects all nodes (stored in FormatToken objects) that could appear on a
+single line if there were no line length restrictions. It's then used by the
+parser to perform the wrapping required to comply with the style guide.
+"""
+
+from lib2to3 import pytree
+
+from yapf.yapflib import format_token
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import split_penalty
+from yapf.yapflib import style
+
+
+class UnwrappedLine(object):
+  """Represents a single unwrapped line in the output.
+
+  Attributes:
+    depth: indentation depth of this line. This is just a numeric value used to
+      distinguish lines that are more deeply nested than others. It is not the
+      actual amount of spaces, which is style-dependent.
+  """
+
+  def __init__(self, depth, tokens=None):
+    """Constructor.
+
+    Creates a new unwrapped line with the given depth an initial list of tokens.
+    Constructs the doubly-linked lists for format tokens using their built-in
+    next_token and previous_token attributes.
+
+    Arguments:
+      depth: indentation depth of this line
+      tokens: initial list of tokens
+    """
+    self.depth = depth
+    self._tokens = tokens or []
+
+    if self._tokens:
+      # Set up a doubly linked list.
+      for index, tok in enumerate(self._tokens[1:]):
+        # Note, 'index' is the index to the previous token.
+        tok.previous_token = self._tokens[index]
+        self._tokens[index].next_token = tok
+
+  def CalculateFormattingInformation(self):
+    """Calculate the split penalty and total length for the tokens."""
+    # Say that the first token in the line should have a space before it. This
+    # means only that if this unwrapped line is joined with a predecessor line,
+    # then there will be a space between them.
+    self.first.spaces_required_before = 1
+    self.first.total_length = len(self.first.value)
+
+    prev_token = self.first
+    prev_length = self.first.total_length
+    for token in self._tokens[1:]:
+      if (token.spaces_required_before == 0 and
+          _SpaceRequiredBetween(prev_token, token)):
+        token.spaces_required_before = 1
+
+      # The split penalty has to be computed before {must|can}_break_before,
+      # because these may use it for their decision.
+      token.split_penalty += _SplitPenalty(prev_token, token)
+      token.must_break_before = _MustBreakBefore(prev_token, token)
+      token.can_break_before = (token.must_break_before or
+                                _CanBreakBefore(prev_token, token))
+
+      token.total_length = (prev_length + len(token.value) +
+                            token.spaces_required_before)
+
+      prev_length = token.total_length
+      prev_token = token
+
+  ############################################################################
+  # Token Access and Manipulation Methods                                    #
+  ############################################################################
+
+  def AppendToken(self, token):
+    """Append a new FormatToken to the tokens contained in this line."""
+    if self._tokens:
+      token.previous_token = self.last
+      self.last.next_token = token
+    self._tokens.append(token)
+
+  def AppendNode(self, node):
+    """Convenience method to append a pytree node directly.
+
+    Wraps the node with a FormatToken.
+
+    Arguments:
+      node: the node to append
+    """
+    assert isinstance(node, pytree.Leaf)
+    self.AppendToken(format_token.FormatToken(node))
+
+  @property
+  def first(self):
+    """Returns the first non-whitespace token."""
+    return self._tokens[0]
+
+  @property
+  def last(self):
+    """Returns the last non-whitespace token."""
+    return self._tokens[-1]
+
+  ############################################################################
+  # Token -> String Methods                                                  #
+  ############################################################################
+
+  def AsCode(self, indent_per_depth=2):
+    """Return a "code" representation of this line.
+
+    The code representation shows how the line would be printed out as code.
+
+    TODO(eliben): for now this is rudimentary for debugging - once we add
+    formatting capabilities, this method will have other uses (not all tokens
+    have spaces around them, for example).
+
+    Arguments:
+      indent_per_depth: how much spaces to indend per depth level.
+
+    Returns:
+      A string representing the line as code.
+    """
+    indent = ' ' * indent_per_depth * self.depth
+    tokens_str = ' '.join(tok.value for tok in self._tokens)
+    return indent + tokens_str
+
+  def __str__(self):
+    return self.AsCode()
+
+  def __repr__(self):
+    tokens_repr = ','.join(['{0}({1!r})'.format(tok.name, tok.value)
+                            for tok in self._tokens])
+    return 'UnwrappedLine(depth={0}, tokens=[{1}])'.format(self.depth,
+                                                           tokens_repr)
+
+  ############################################################################
+  # Properties                                                               #
+  ############################################################################
+
+  @property
+  def tokens(self):
+    """Access the tokens contained within this line.
+
+    The caller must not modify the tokens list returned by this method.
+
+    Returns:
+      List of tokens in this line.
+    """
+    return self._tokens
+
+  @property
+  def lineno(self):
+    """Return the line number of this unwrapped line.
+
+    Returns:
+      The line number of the first token in this unwrapped line.
+    """
+    return self.first.lineno
+
+  @property
+  def is_comment(self):
+    return self.first.is_comment
+
+
+def _IsIdNumberStringToken(tok):
+  return tok.is_keyword or tok.is_name or tok.is_number or tok.is_string
+
+
+def _IsUnaryOperator(tok):
+  return tok.subtype == format_token.Subtype.UNARY_OPERATOR
+
+
+def _IsBinaryOperator(tok):
+  return tok.subtype == format_token.Subtype.BINARY_OPERATOR
+
+
+def _SpaceRequiredBetween(left, right):
+  """Return True if a space is required between the left and right token."""
+  if right.name in pytree_utils.NONSEMANTIC_TOKENS:
+    # No space before a non-semantic token.
+    return False
+  if _IsIdNumberStringToken(left) and _IsIdNumberStringToken(right):
+    # Spaces between keyword, string, number, and identifier tokens.
+    return True
+  if right.value in ':,':
+    # We never want a space before a colon or comma.
+    return False
+  if left.value == ',' and right.value in ']})':
+    # We don't want a space between a comma and the ending bracket.
+    return False
+  if left.value == ',':
+    # We want a space after a comma.
+    return True
+  if left.value == 'from' and right.value == '.':
+    # Space before the '.' in an import statement.
+    return True
+  if ((right.is_keyword or right.is_name) and
+      (left.is_keyword or left.is_name)):
+    # Don't merge two keywords/identifiers.
+    return True
+  if left.is_string and right.value not in '[)]}.':
+    # A string followed by something other than a subscript, closing bracket,
+    # or dot should have a space after it.
+    return True
+  if _IsBinaryOperator(left) and _IsUnaryOperator(right):
+    # Space between the binary opertor and the unary operator.
+    return True
+  if _IsUnaryOperator(left) and _IsUnaryOperator(right):
+    # No space between two unary operators.
+    return False
+  if _IsBinaryOperator(left) or _IsBinaryOperator(right):
+    # Enforce spaces around binary operators.
+    return True
+  if _IsUnaryOperator(left) and (right.is_name or right.is_number or
+                                 right.value == '('):
+    # The previous token was a unary op. No space is desired between it and
+    # the current token.
+    return False
+  if (left.subtype == format_token.Subtype.SUBSCRIPT_COLON or
+      right.subtype == format_token.Subtype.SUBSCRIPT_COLON):
+    # A subscript shouldn't have spaces separating its colons.
+    return False
+  if (left.subtype == format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN or
+      right.subtype == format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN):
+    # A named argument or default parameter shouldn't have spaces around it.
+    return False
+  if left.subtype in {
+      format_token.Subtype.VARARGS_STAR, format_token.Subtype.KWARGS_STAR_STAR
+  }:
+    # Don't add a space after a vararg's star or a keyword's star-star.
+    return False
+  if left.value == '@':
+    # Decorators shouldn't be separated from the 'at' sign.
+    return False
+  if left.value == '.' or right.value == '.':
+    # Don't place spaces between dots.
+    return False
+  if ((left.value == '(' and right.value == ')') or
+      (left.value == '[' and right.value == ']') or
+      (left.value == '{' and right.value == '}')):
+    # Empty objects shouldn't be separted by spaces.
+    return False
+  if (left.value in pytree_utils.OPENING_BRACKETS and
+      right.value in pytree_utils.OPENING_BRACKETS):
+    # Nested objects' opening brackets shouldn't be separated.
+    return False
+  if (left.value in pytree_utils.CLOSING_BRACKETS and
+      right.value in pytree_utils.CLOSING_BRACKETS):
+    # Nested objects' closing brackets shouldn't be separated.
+    return False
+  if left.value in pytree_utils.CLOSING_BRACKETS and right.value in '([':
+    # A call, set, dictionary, or subscript that has a call or subscript after
+    # it shouldn't have a space between them.
+    return False
+  if (left.value in pytree_utils.OPENING_BRACKETS and
+      _IsIdNumberStringToken(right)):
+    # Don't separate the opening bracket from the first item.
+    return False
+  if left.is_name and right.value in '([':
+    # Don't separate a call or array access from the name.
+    return False
+  if right.value in pytree_utils.CLOSING_BRACKETS:
+    # Don't separate the closing bracket from the last item.
+    # FIXME(morbo): This might be too permissive.
+    return False
+  if left.value == 'print' and right.value == '(':
+    # Special support for the 'print' function.
+    return False
+  if left.value in pytree_utils.OPENING_BRACKETS and _IsUnaryOperator(right):
+    # Don't separate a unary operator from the opening bracket.
+    return False
+  if (left.value in pytree_utils.OPENING_BRACKETS and right.subtype in {
+      format_token.Subtype.VARARGS_STAR, format_token.Subtype.KWARGS_STAR_STAR
+  }):
+    # Don't separate a '*' or '**' from the opening bracket.
+    return False
+  return True
+
+
+def _MustBreakBefore(prev_token, cur_token):
+  """Return True if a line break is required before the current token."""
+  if prev_token.is_comment:
+    # Must break if the previous token was a comment.
+    return True
+  if cur_token.is_string and prev_token.is_string:
+    # We want consecutive strings to be on separate lines. This is a
+    # reasonable assumption, because otherwise they should have written them
+    # all on the same line, or with a '+'.
+    return True
+  # TODO(morbo): There may be more to add here.
+  return False
+
+
+def _CanBreakBefore(prev_token, cur_token):
+  """Return True if a line break may occur before the current token."""
+  if cur_token.split_penalty >= split_penalty.UNBREAKABLE:
+    return False
+  if prev_token.value == '@':
+    # Don't break right after the beginning of a decorator.
+    return False
+  if cur_token.value == ':':
+    # Don't break before the start of a block of code.
+    return False
+  if cur_token.value == ',':
+    # Don't break before a comma.
+    return False
+  if prev_token.is_name and cur_token.value == '(':
+    # Don't break in the middle of a function definition or call.
+    return False
+  if prev_token.is_name and cur_token.value == '[':
+    # Don't break in the middle of an array dereference.
+    return False
+  if prev_token.is_name and cur_token.value == '.':
+    # Don't break before the '.' in a dotted name.
+    return False
+  # TODO(morbo): There may be more to add here.
+  return True
+
+
+_LOGICAL_OPERATORS = frozenset({'and', 'or'})
+
+
+def _SplitPenalty(prev_token, cur_token):
+  """Return the penalty for breaking the line before the current token."""
+  if cur_token.node_split_penalty is not None:
+    return cur_token.node_split_penalty
+
+  if style.SPLIT_BEFORE_LOGICAL_OPERATOR:
+    # Prefer to split before 'and' and 'or'.
+    if prev_token.value in _LOGICAL_OPERATORS:
+      return style.SPLIT_PENALTY_LOGICAL_OPERATOR
+    if cur_token.value in _LOGICAL_OPERATORS:
+      return 0
+  else:
+    # Prefer to split after 'and' and 'or'.
+    if prev_token.value in _LOGICAL_OPERATORS:
+      return 0
+    if cur_token.value in _LOGICAL_OPERATORS:
+      return style.SPLIT_PENALTY_LOGICAL_OPERATOR
+
+  if prev_token.subtype is format_token.Subtype.UNARY_OPERATOR:
+    # Try not to break after a unary operator.
+    return style.SPLIT_PENALTY_AFTER_UNARY_OPERATOR
+  if prev_token.value == ',':
+    # Breaking after a comma is fine, if need be.
+    return 0
+  if prev_token.value == ':':
+    # We would rather not split after a colon.
+    return split_penalty.STRONGLY_CONNECTED
+  if prev_token.value == '==':
+    # We would rather not split after an equality operator.
+    return 20
+  if prev_token.subtype in {
+      format_token.Subtype.VARARGS_STAR, format_token.Subtype.KWARGS_STAR_STAR
+  }:
+    # Don't split after a varargs * or kwargs **.
+    return split_penalty.UNBREAKABLE
+  if prev_token.value in pytree_utils.OPENING_BRACKETS:
+    # Slightly prefer
+    return style.SPLIT_PENALTY_AFTER_OPENING_BRACKET
+  if cur_token.value == ':':
+    # Don't split before a colon.
+    return split_penalty.UNBREAKABLE
+  if cur_token.value == '=':
+    # Don't split before an assignment.
+    return split_penalty.UNBREAKABLE
+  if (prev_token.subtype == format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN or
+      cur_token.subtype == format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN):
+    # Don't break before or after an default or named assignment.
+    return split_penalty.UNBREAKABLE
+  if cur_token.value == '==':
+    # We would rather not split before an equality operator.
+    return split_penalty.STRONGLY_CONNECTED
+  return 0
diff --git a/yapf/yapflib/verifier.py b/yapf/yapflib/verifier.py
new file mode 100644
index 0000000..b32e9e5
--- /dev/null
+++ b/yapf/yapflib/verifier.py
@@ -0,0 +1,72 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Verify that the generated code is valid code.
+
+This takes a line of code and "normalizes" it. I.e., it transforms the snippet
+into something that has the potential to compile.
+
+    VerifyCode(): the main function exported by this module.
+"""
+
+import ast
+import re
+import sys
+import textwrap
+
+
+def VerifyCode(code):
+  """Verify that the reformatted code is syntactically correct.
+
+  Arguments:
+    code: (unicode) The reformatted code snippet.
+
+  Raises:
+    SyntaxError if the code was reformatted incorrectly.
+  """
+  try:
+    compile(textwrap.dedent(code).encode('UTF-8'), '<string>', 'exec')
+  except SyntaxError:
+    try:
+      ast.parse(textwrap.dedent(code.lstrip('\n')).lstrip(), '<string>', 'exec')
+    except SyntaxError:
+      try:
+        normalized_code = _NormalizeCode(code)
+        compile(normalized_code.encode('UTF-8'), '<string>', 'exec')
+      except SyntaxError:
+        sys.stderr.write('INTERNAL ERROR: %s\n' % code)
+        raise
+
+
+def _NormalizeCode(code):
+  """Make sure that the code snippet is compilable."""
+  code = textwrap.dedent(code.lstrip('\n')).lstrip()
+
+  if re.match(r'(if|while|for|with|def|class)\b', code):
+    code += '\n    pass'
+  elif re.match(r'(elif|else)\b', code):
+    code = 'if True:\n    pass\n' + code + '\n    pass'
+  elif code.startswith('@'):
+    code += '\ndef _():\n    pass'
+  elif re.match(r'try\b', code):
+    code += '\n    pass\nexcept:\n    pass'
+  elif re.match(r'(except|finally)\b', code):
+    code = 'try:\n    pass\n' + code + '\n    pass'
+  elif re.match(r'(return|yield)\b', code):
+    code = 'def _():\n    ' + code
+  elif re.match(r'(continue|break)\b', code):
+    code = 'while True:\n    ' + code
+  elif re.match(r'print\b', code):
+    code = 'from __future__ import print_function\n' + code
+
+  return code + '\n'
diff --git a/yapf/yapflib/yapf_api.py b/yapf/yapflib/yapf_api.py
new file mode 100644
index 0000000..69ac3c3
--- /dev/null
+++ b/yapf/yapflib/yapf_api.py
@@ -0,0 +1,234 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Entry points for Yet Another Python Formatter.
+
+The main APIs that YAPF exposes to drive the reformatting.
+
+  FormatFile(): reformat a file.
+  FormatCode(): reformat a string of code.
+"""
+
+import difflib
+import io
+import logging
+import re
+
+from yapf.yapflib import blank_line_calculator
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import line_joiner
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import reformatter
+from yapf.yapflib import split_penalty
+from yapf.yapflib import style
+from yapf.yapflib import subtype_assigner
+
+
+def FormatFile(filename, lines=None, print_diff=False):
+  """Format a single Python file and returns the formatted code.
+
+  Arguments:
+    filename: (unicode) The file to reformat.
+    lines: (list of tuples of integers) A list of tuples of lines, [start, end],
+      that we want to format. The lines are 1-based indexed. This argument
+      overrides the 'FLAGS.lines'. It can be used by third-party code (e.g.,
+      IDEs) when reformatting a snippet of code.
+    print_diff: (bool) Print the diff for the fixed source.
+
+  Returns:
+    The reformatted code or None if the file doesn't exist.
+  """
+  original_source = ReadFile(filename, logging.warning)
+  if original_source is None:
+    return None
+
+  return FormatCode(original_source, filename=filename, lines=lines,
+                    print_diff=print_diff)
+
+
+def FormatCode(unformatted_source, filename='<unknown>', lines=None,
+               print_diff=False, indent_width=2):
+  """Format a string of Python code.
+
+  This provides an alternative entry point to YAPF.
+
+  Arguments:
+    unformatted_source: (unicode) The code to format.
+    filename: (unicode) The name of the file being reformatted.
+    lines: (list of tuples of integers) A list of tuples of lines, [start, end],
+      that we want to format. The lines are 1-based indexed. This argument
+      overrides the 'FLAGS.lines'. It can be used by third-party code (e.g.,
+      IDEs) when reformatting a snippet of code.
+    print_diff: (bool) Print the diff for the fixed source.
+    indent_width: (int) The width of the indent.
+
+  Returns:
+    The code reformatted to conform to the desired formatting style.
+  """
+  style.INDENT_WIDTH = indent_width
+  tree = pytree_utils.ParseCodeToTree(unformatted_source)
+
+  # Run passes on the tree, modifying it in place.
+  comment_splicer.SpliceComments(tree)
+  subtype_assigner.AssignSubtypes(tree)
+  split_penalty.ComputeSplitPenalties(tree)
+  blank_line_calculator.CalculateBlankLines(tree)
+
+  uwlines = pytree_unwrapper.UnwrapPyTree(tree)
+  if not uwlines:
+    return ''
+  for uwl in uwlines:
+    uwl.CalculateFormattingInformation()
+
+  line_joiner.CanMergeMultipleLines(uwlines)
+
+  if lines is not None:
+    reformatted_source = _FormatLineSnippets(unformatted_source, uwlines, lines)
+  else:
+    lines = _LinesToSkip(uwlines)
+    if lines:
+      reformatted_source = _FormatLineSnippets(unformatted_source, uwlines,
+                                               lines)
+    else:
+      reformatted_source = reformatter.Reformat(uwlines)
+
+  if unformatted_source == reformatted_source:
+    return '' if print_diff else reformatted_source
+
+  code_diff = _GetUnifiedDiff(unformatted_source, reformatted_source,
+                              filename=filename)
+
+  if print_diff:
+    return code_diff
+
+  return reformatted_source
+
+
+def ReadFile(filename, logger=None):
+  """Read the contents of the file.
+
+  An optional logger can be specified to emit messages to your favorite logging
+  stream. If specified, then no exception is raised.
+
+  Arguments:
+    filename: (unicode) The name of the file.
+    logger: (function) A function or lambda that takes a string and emits it.
+
+  Returns:
+    The contents of filename.
+
+  Raises:
+    IOError: raised during an error if a logger is not specified.
+  """
+  try:
+    with io.open(filename, mode='r', newline='') as fd:
+      source = fd.read()
+    return source
+  except IOError as err:
+    if logger:
+      logger(err)
+    else:
+      raise
+
+
+DISABLE_PATTERN = r'^#+ +(?:yapf|pyformat): *disable$'
+ENABLE_PATTERN = r'^#+ +(?:yapf|pyformat): *enable$'
+
+
+def _LinesToSkip(uwlines):
+  """Skip sections of code that we shouldn't reformat."""
+  start = 1
+  lines = []
+  for uwline in uwlines:
+    if uwline.is_comment:
+      if re.search(DISABLE_PATTERN, uwline.first.value.strip(), re.IGNORECASE):
+        lines.append((start, uwline.lineno))
+      elif re.search(ENABLE_PATTERN, uwline.first.value.strip(), re.IGNORECASE):
+        start = uwline.lineno
+    elif re.search(DISABLE_PATTERN, uwline.last.value.strip(), re.IGNORECASE):
+      # Disable only one line.
+      if uwline.lineno != start:
+        lines.append((start, uwline.lineno - 1))
+      start = uwline.last.lineno + 1
+
+  if start != 1 and start <= uwlines[-1].last.lineno + 1:
+    lines.append((start, uwlines[-1].last.lineno))
+  return lines
+
+
+def _FormatLineSnippets(unformatted_source, uwlines, lines):
+  """Format a string of Python code.
+
+  This provides an alternative entry point to YAPF.
+
+  Arguments:
+    unformatted_source: (unicode) The code to format.
+    uwlines: (list of UnwrappedLine) The unwrapped lines.
+    lines: (list of tuples of integers) A list of lines that we want to format.
+      The lines are 1-indexed.
+
+  Returns:
+    The code reformatted to conform to the desired formatting style.
+  """
+  # First we reformat only those lines that we want to reformat.
+  index = 0
+  reformatted_sources = dict()
+  for start, end in sorted(lines):
+    snippet = []
+    while index < len(uwlines):
+      if start <= uwlines[index].lineno or start < uwlines[index].last.lineno:
+        while index < len(uwlines):
+          if end < uwlines[index].lineno:
+            break
+          snippet.append(uwlines[index])
+          index += 1
+        break
+      index += 1
+    reformatted_sources[(start, end)] = reformatter.Reformat(snippet).rstrip()
+
+  # Next we reconstruct the finalized lines inserting the reformatted lines at
+  # the appropriate places.
+  prev_end = 0
+  finalized_lines = []
+  unformatted_lines = unformatted_source.splitlines()
+  for key in sorted(reformatted_sources):
+    start, end = key
+    finalized_lines.extend(unformatted_lines[prev_end:start - 1])
+    finalized_lines.append(reformatted_sources[key])
+    prev_end = end
+
+  # If there are any remaining lines, place them at the end.
+  if prev_end < len(unformatted_lines):
+    finalized_lines.extend(unformatted_lines[prev_end:])
+
+  # Construct the reformatted sources.
+  return '\n'.join(finalized_lines).rstrip() + '\n'
+
+
+def _GetUnifiedDiff(before, after, filename='code'):
+  """Get a unified diff of the changes.
+
+  Arguments:
+    before: (unicode) The original source code.
+    after: (unicode) The reformatted source code.
+    filename: (unicode) The code's filename.
+
+  Returns:
+    The unified diff text.
+  """
+  before = before.splitlines()
+  after = after.splitlines()
+  return '\n'.join(difflib.unified_diff(before, after, filename, filename,
+                                        '(original)', '(reformatted)',
+                                        lineterm='')) + '\n'
diff --git a/yapftests/__init__.py b/yapftests/__init__.py
new file mode 100644
index 0000000..6eceb4e
--- /dev/null
+++ b/yapftests/__init__.py
@@ -0,0 +1,56 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import unittest
+
+from yapftests import blank_line_calculator_test
+from yapftests import blank_line_calculator_test
+from yapftests import comment_splicer_test
+from yapftests import format_decision_state_test
+from yapftests import format_token_test
+from yapftests import line_joiner_test
+from yapftests import pytree_unwrapper_test
+from yapftests import pytree_utils_test
+from yapftests import pytree_visitor_test
+from yapftests import reformatter_test
+from yapftests import split_penalty_test
+from yapftests import subtype_assigner_test
+from yapftests import unwrapped_line_test
+from yapftests import yapf_test
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(blank_line_calculator_test.suite())
+  result.addTests(blank_line_calculator_test.suite())
+  result.addTests(comment_splicer_test.suite())
+  result.addTests(format_decision_state_test.suite())
+  result.addTests(format_token_test.suite())
+  result.addTests(line_joiner_test.suite())
+  result.addTests(pytree_unwrapper_test.suite())
+  result.addTests(pytree_utils_test.suite())
+  result.addTests(pytree_visitor_test.suite())
+  result.addTests(reformatter_test.suite())
+  result.addTests(split_penalty_test.suite())
+  result.addTests(subtype_assigner_test.suite())
+  result.addTests(unwrapped_line_test.suite())
+  result.addTests(yapf_test.suite())
+  return result
+
+
+if __name__ == '__main__':
+  runner = unittest.TextTestRunner()
+  result = runner.run(suite())
+  sys.exit(not result.wasSuccessful())
diff --git a/yapftests/blank_line_calculator_test.py b/yapftests/blank_line_calculator_test.py
new file mode 100644
index 0000000..cfd9d6a
--- /dev/null
+++ b/yapftests/blank_line_calculator_test.py
@@ -0,0 +1,276 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.blank_line_calculator."""
+
+import sys
+import textwrap
+import unittest
+
+from yapf.yapflib import blank_line_calculator
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import reformatter
+from yapf.yapflib import split_penalty
+from yapf.yapflib import subtype_assigner
+
+
+class BlankLineCalculatorTest(unittest.TestCase):
+
+  def testDecorators(self):
+    unformatted_code = textwrap.dedent("""\
+        @bork()
+
+        def foo():
+          pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        @bork()
+        def foo():
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testComplexDecorators(self):
+    unformatted_code = textwrap.dedent("""\
+        import sys
+        @bork()
+
+        def foo():
+          pass
+        @fork()
+
+        class moo(object):
+          @bar()
+          @baz()
+
+          def method(self):
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        import sys
+
+
+        @bork()
+        def foo():
+          pass
+
+
+        @fork()
+        class moo(object):
+
+          @bar()
+          @baz()
+          def method(self):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testCodeAfterFunctionsAndClasses(self):
+    unformatted_code = textwrap.dedent("""\
+        def foo():
+          pass
+        top_level_code = True
+        class moo(object):
+          def method_1(self):
+            pass
+          ivar_a = 42
+          ivar_b = 13
+          def method_2(self):
+            pass
+        try:
+          raise Error
+        except Error as error:
+          pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def foo():
+          pass
+
+
+        top_level_code = True
+
+
+        class moo(object):
+
+          def method_1(self):
+            pass
+
+          ivar_a = 42
+          ivar_b = 13
+
+          def method_2(self):
+            pass
+
+
+        try:
+          raise Error
+        except Error as error:
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testCommentSpacing(self):
+    unformatted_code = textwrap.dedent("""\
+        # This is the first comment
+        # And it's multiline
+
+        # This is the second comment
+
+        def foo():
+          pass
+
+        # multiline before a
+        # class definition
+
+        # This is the second comment
+
+        class qux(object):
+          pass
+
+
+        # An attached comment.
+        class bar(object):
+          '''class docstring'''
+          # Comment attached to
+          # function
+          def foo(self):
+            '''Another docstring.'''
+            # Another multiline
+            # comment
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        # This is the first comment
+        # And it's multiline
+
+        # This is the second comment
+
+
+        def foo():
+          pass
+
+        # multiline before a
+        # class definition
+
+        # This is the second comment
+
+
+        class qux(object):
+          pass
+
+
+        # An attached comment.
+        class bar(object):
+          '''class docstring'''
+
+          # Comment attached to
+          # function
+          def foo(self):
+            '''Another docstring.'''
+            # Another multiline
+            # comment
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testCommentBeforeMethod(self):
+    code = textwrap.dedent("""\
+        class foo(object):
+
+          # pylint: disable=invalid-name
+          def f(self):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testCommentsBeforeClassDefs(self):
+    code = textwrap.dedent('''\
+        """Test."""
+
+        # Comment
+
+
+        class Foo(object):
+          pass
+        ''')
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testComemntsBeforeDecorator(self):
+    code = textwrap.dedent("""\
+        # The @foo operator adds bork to a().
+        @foo()
+        def a():
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+    code = textwrap.dedent("""\
+        # Hello world
+
+
+        @foo()
+        def a():
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+
+def _ParseAndUnwrap(code, dumptree=False):
+  """Produces unwrapped lines from the given code.
+
+  Parses the code into a tree, performs comment splicing and runs the
+  unwrapper.
+
+  Arguments:
+    code: code to parse as a string
+    dumptree: if True, the parsed pytree (after comment splicing) is dumped
+      to stderr. Useful for debugging.
+
+  Returns:
+    List of unwrapped lines.
+  """
+  tree = pytree_utils.ParseCodeToTree(code)
+  comment_splicer.SpliceComments(tree)
+  subtype_assigner.AssignSubtypes(tree)
+  split_penalty.ComputeSplitPenalties(tree)
+  blank_line_calculator.CalculateBlankLines(tree)
+
+  if dumptree:
+    pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+  uwlines = pytree_unwrapper.UnwrapPyTree(tree)
+  for uwl in uwlines:
+    uwl.CalculateFormattingInformation()
+
+  return uwlines
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(BlankLineCalculatorTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/comment_splicer_test.py b/yapftests/comment_splicer_test.py
new file mode 100644
index 0000000..c82cf7b
--- /dev/null
+++ b/yapftests/comment_splicer_test.py
@@ -0,0 +1,312 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.comment_splicer."""
+
+import itertools
+import textwrap
+import unittest
+
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import pytree_utils
+
+
+class CommentSplicerTest(unittest.TestCase):
+
+  def _AssertNodeType(self, expected_type, node):
+    self.assertEqual(expected_type, pytree_utils.NodeName(node))
+
+  def _AssertNodeIsComment(self, node, text_in_comment=None):
+    if pytree_utils.NodeName(node) == 'simple_stmt':
+      self._AssertNodeType('COMMENT', node.children[0])
+      node_value = node.children[0].value
+    else:
+      self._AssertNodeType('COMMENT', node)
+      node_value = node.value
+    if text_in_comment is not None:
+      self.assertIn(text_in_comment, node_value)
+
+  def _FindNthChildNamed(self, node, name, n=1):
+    for i, child in enumerate(itertools.ifilter(
+        lambda c: pytree_utils.NodeName(c) == name, node.pre_order())):
+      if i == n - 1:
+        return child
+    raise RuntimeError('No Nth child for n={0}'.format(n))
+
+  def testSimpleInline(self):
+    code = 'foo = 1 # and a comment\n'
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    expr = tree.children[0].children[0]
+    # Check that the expected node is still expr_stmt, but now it has 4 children
+    # (before comment splicing it had 3), the last child being the comment.
+    self._AssertNodeType('expr_stmt', expr)
+    self.assertEqual(4, len(expr.children))
+    comment_node = expr.children[3]
+    self._AssertNodeIsComment(comment_node, '# and a comment')
+
+  def testSimpleSeparateLine(self):
+    code = textwrap.dedent(r'''
+      foo = 1
+      # first comment
+      bar = 2
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # The comment should've been added to the root's children (now 4, including
+    # the ENDMARKER in the end.
+    self.assertEqual(4, len(tree.children))
+    comment_node = tree.children[1]
+    self._AssertNodeIsComment(comment_node)
+
+  def testTwoLineComment(self):
+    code = textwrap.dedent(r'''
+      foo = 1
+      # first comment
+      # second comment
+      bar = 2
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # This is similar to the single-line standalone comment.
+    self.assertEqual(4, len(tree.children))
+    self._AssertNodeIsComment(tree.children[1])
+
+  def testCommentIsFirstChildInCompound(self):
+    code = textwrap.dedent(r'''
+      if x:
+        # a comment
+        foo = 1
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # Look into the suite node under the 'if'. We don't care about the NEWLINE
+    # leaf but the new COMMENT must be a child of the suite and before the
+    # actual code leaf.
+    if_suite = tree.children[0].children[3]
+    self._AssertNodeType('NEWLINE', if_suite.children[0])
+    self._AssertNodeIsComment(if_suite.children[1])
+
+  def testCommentIsLastChildInCompound(self):
+    code = textwrap.dedent(r'''
+      if x:
+        foo = 1
+        # a comment
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # Look into the suite node under the 'if'. We don't care about the DEDENT
+    # leaf but the new COMMENT must be a child of the suite and after the
+    # actual code leaf.
+    if_suite = tree.children[0].children[3]
+    self._AssertNodeType('DEDENT', if_suite.children[-1])
+    self._AssertNodeIsComment(if_suite.children[-2])
+
+  def testInlineAfterSeparateLine(self):
+    code = textwrap.dedent(r'''
+      bar = 1
+      # line comment
+      foo = 1 # inline comment
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # The separate line comment should become a child of the root, while
+    # the inline comment remains within its simple_node.
+    sep_comment_node = tree.children[1]
+    self._AssertNodeIsComment(sep_comment_node, '# line comment')
+
+    expr = tree.children[2].children[0]
+    inline_comment_node = expr.children[-1]
+    self._AssertNodeIsComment(inline_comment_node, '# inline comment')
+
+  def testSeparateLineAfterInline(self):
+    code = textwrap.dedent(r'''
+      bar = 1
+      foo = 1 # inline comment
+      # line comment
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # The separate line comment should become a child of the root, while
+    # the inline comment remains within its simple_node.
+    sep_comment_node = tree.children[-2]
+    self._AssertNodeIsComment(sep_comment_node, '# line comment')
+
+    expr = tree.children[1].children[0]
+    inline_comment_node = expr.children[-1]
+    self._AssertNodeIsComment(inline_comment_node, '# inline comment')
+
+  def testCommentBeforeDedent(self):
+    code = textwrap.dedent(r'''
+      if bar:
+        z = 1
+      # a comment
+      j = 2
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # The comment should go under the tree root, not under the 'if'.
+    self._AssertNodeIsComment(tree.children[1])
+    if_suite = tree.children[0].children[3]
+    self._AssertNodeType('DEDENT', if_suite.children[-1])
+
+  def testCommentBeforeDedentTwoLevel(self):
+    code = textwrap.dedent(r'''
+      if foo:
+        if bar:
+          z = 1
+        # a comment
+      y = 1
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    if_suite = tree.children[0].children[3]
+    # The comment is in the first if_suite, not the nested if under it. It's
+    # right before the DEDENT
+    self._AssertNodeIsComment(if_suite.children[-2])
+    self._AssertNodeType('DEDENT', if_suite.children[-1])
+
+  def testCommentBeforeDedentTwoLevelImproperlyIndented(self):
+    code = textwrap.dedent(r'''
+      if foo:
+        if bar:
+          z = 1
+         # comment 2
+      y = 1
+      ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    # The comment here is indented by 3 spaces, which is unlike any of the
+    # surrounding statement indentation levels. The splicer attaches it to the
+    # "closest" parent with smaller indentation.
+    if_suite = tree.children[0].children[3]
+    # The comment is in the first if_suite, not the nested if under it. It's
+    # right before the DEDENT
+    self._AssertNodeIsComment(if_suite.children[-2])
+    self._AssertNodeType('DEDENT', if_suite.children[-1])
+
+  def testCommentsInClass(self):
+    code = textwrap.dedent(r'''
+      class Foo:
+        """docstring abc..."""
+        # top-level comment
+        def foo(): pass
+        # another comment
+      ''')
+
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    class_suite = tree.children[0].children[3]
+    another_comment = class_suite.children[-2]
+    self._AssertNodeIsComment(another_comment, '# another')
+
+    # It's OK for the comment to be a child of funcdef, as long as it's
+    # the first child and thus comes before the 'def'.
+    funcdef = class_suite.children[3]
+    toplevel_comment = funcdef.children[0]
+    self._AssertNodeIsComment(toplevel_comment, '# top-level')
+
+  def testMultipleBlockComments(self):
+    code = textwrap.dedent(r'''
+        # Block comment number 1
+
+        # Block comment number 2
+        def f():
+          pass
+        ''')
+
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    funcdef = tree.children[0]
+    block_comment_1 = funcdef.children[0]
+    self._AssertNodeIsComment(block_comment_1, '# Block comment number 1')
+
+    block_comment_2 = funcdef.children[1]
+    self._AssertNodeIsComment(block_comment_2, '# Block comment number 2')
+
+  def testCommentsOnDedents(self):
+    code = textwrap.dedent(r'''
+        class Foo(object):
+          # A comment for qux.
+          def qux(self):
+            pass
+
+          # Interim comment.
+
+          def mux(self):
+            pass
+        ''')
+
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    classdef = tree.children[0]
+    class_suite = classdef.children[6]
+    qux_comment = class_suite.children[1]
+    self._AssertNodeIsComment(qux_comment, '# A comment for qux.')
+
+    interim_comment = class_suite.children[4]
+    self._AssertNodeIsComment(interim_comment, '# Interim comment.')
+
+  def testExprComments(self):
+    code = textwrap.dedent(r'''
+      foo( # Request fractions of an hour.
+        948.0/3600, 20)
+    ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    trailer = self._FindNthChildNamed(tree, 'trailer', 1)
+    comment = trailer.children[1]
+    self._AssertNodeIsComment(comment, '# Request fractions of an hour.')
+
+  def testMultipleCommentsInOneExpr(self):
+    code = textwrap.dedent(r'''
+      foo( # com 1
+        948.0/3600, # com 2
+        20 + 12 # com 3
+        )
+    ''')
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    trailer = self._FindNthChildNamed(tree, 'trailer', 1)
+    self._AssertNodeIsComment(trailer.children[1], '# com 1')
+
+    arglist = self._FindNthChildNamed(tree, 'arglist', 1)
+    self._AssertNodeIsComment(arglist.children[2], '# com 2')
+
+    arith_expr = self._FindNthChildNamed(tree, 'arith_expr', 1)
+    self._AssertNodeIsComment(arith_expr.children[-1], '# com 3')
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(CommentSplicerTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/format_decision_state_test.py b/yapftests/format_decision_state_test.py
new file mode 100644
index 0000000..a99c1ca
--- /dev/null
+++ b/yapftests/format_decision_state_test.py
@@ -0,0 +1,169 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.format_decision_state."""
+
+import sys
+import textwrap
+import unittest
+
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import format_decision_state
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import split_penalty
+from yapf.yapflib import subtype_assigner
+from yapf.yapflib import unwrapped_line
+
+
+class FormatDecisionStateTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code, dumptree=False):
+    """Produces unwrapped lines from the given code.
+
+    Parses the code into a tree, performs comment splicing and runs the
+    unwrapper.
+
+    Arguments:
+      code: code to parse as a string
+      dumptree: if True, the parsed pytree (after comment splicing) is dumped
+        to stderr. Useful for debugging.
+
+    Returns:
+      List of unwrapped lines.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+    subtype_assigner.AssignSubtypes(tree)
+    split_penalty.ComputeSplitPenalties(tree)
+
+    if dumptree:
+      pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+    return pytree_unwrapper.UnwrapPyTree(tree)
+
+  def _FilterLine(self, uwline):
+    """Filter out nonsemantic tokens from the UnwrappedLines."""
+    return [ft for ft in uwline.tokens
+            if ft.name not in pytree_utils.NONSEMANTIC_TOKENS]
+
+  def testSimpleFunctionDefWithNoSplitting(self):
+    code = textwrap.dedent(r"""
+      def f(a, b):
+        pass
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    uwline = unwrapped_line.UnwrappedLine(0, self._FilterLine(uwlines[0]))
+    uwline.CalculateFormattingInformation()
+
+    # Add: 'f'
+    state = format_decision_state.FormatDecisionState(uwline, 0)
+    self.assertEqual('f', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+
+    # Add: '('
+    state.AddTokenToState(False, True)
+    self.assertEqual('(', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    # Add: 'a'
+    state.AddTokenToState(False, True)
+    self.assertEqual('a', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    # Add: ','
+    state.AddTokenToState(False, True)
+    self.assertEqual(',', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    # Add: 'b'
+    state.AddTokenToState(False, True)
+    self.assertEqual('b', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    # Add: ')'
+    state.AddTokenToState(False, True)
+    self.assertEqual(')', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    # Add: ':'
+    state.AddTokenToState(False, True)
+    self.assertEqual(':', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.MustSplit())
+
+    clone = state.Clone()
+    self.assertEqual(repr(state), repr(clone))
+
+  def testSimpleFunctionDefWithSplitting(self):
+    code = textwrap.dedent(r"""
+      def f(a, b):
+        pass
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    uwline = unwrapped_line.UnwrappedLine(0, self._FilterLine(uwlines[0]))
+    uwline.CalculateFormattingInformation()
+
+    # Add: 'f'
+    state = format_decision_state.FormatDecisionState(uwline, 0)
+    self.assertEqual('f', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+
+    # Add: '('
+    state.AddTokenToState(True, True)
+    self.assertEqual('(', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+
+    # Add: 'a'
+    state.AddTokenToState(True, True)
+    self.assertEqual('a', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+
+    # Add: ','
+    state.AddTokenToState(True, True)
+    self.assertEqual(',', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+
+    # Add: 'b'
+    state.AddTokenToState(True, True)
+    self.assertEqual('b', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+
+    # Add: ')'
+    state.AddTokenToState(True, True)
+    self.assertEqual(')', state.next_token.value)
+    self.assertTrue(state.CanSplit())
+
+    # Add: ':'
+    state.AddTokenToState(True, True)
+    self.assertEqual(':', state.next_token.value)
+    self.assertFalse(state.CanSplit())
+
+    clone = state.Clone()
+    self.assertEqual(repr(state), repr(clone))
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(FormatDecisionStateTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/format_token_test.py b/yapftests/format_token_test.py
new file mode 100644
index 0000000..211414f
--- /dev/null
+++ b/yapftests/format_token_test.py
@@ -0,0 +1,42 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.format_token."""
+
+import unittest
+
+from lib2to3 import pytree
+from lib2to3.pgen2 import token
+from yapf.yapflib import format_token
+
+
+class FormatTokenTest(unittest.TestCase):
+
+  def testSimple(self):
+    tok = format_token.FormatToken(pytree.Leaf(token.STRING, "'hello world'"))
+    self.assertEqual("FormatToken(name=STRING, value='hello world')", str(tok))
+    self.assertTrue(tok.is_string)
+
+    tok = format_token.FormatToken(pytree.Leaf(token.COMMENT, "# A comment"))
+    self.assertEqual("FormatToken(name=COMMENT, value=# A comment)", str(tok))
+    self.assertTrue(tok.is_comment)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(FormatTokenTest))
+  return result
+
+
+if __name__ == "__main__":
+  unittest.main()
diff --git a/yapftests/line_joiner_test.py b/yapftests/line_joiner_test.py
new file mode 100644
index 0000000..13e1a40
--- /dev/null
+++ b/yapftests/line_joiner_test.py
@@ -0,0 +1,95 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.line_joiner."""
+
+import textwrap
+import unittest
+
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import line_joiner
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+
+
+class LineJoinerTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code):
+    """Produces unwrapped lines from the given code.
+
+    Parses the code into a tree, performs comment splicing and runs the
+    unwrapper.
+
+    Arguments:
+      code: code to parse as a string
+
+    Returns:
+      List of unwrapped lines.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+    return pytree_unwrapper.UnwrapPyTree(tree)
+
+  def _CheckLineJoining(self, code, join_lines):
+    """Check that the given UnwrappedLines are joined as expected.
+
+    Arguments:
+      code: The code to check to see if we can join it.
+      join_lines: True if we expect the lines to be joined.
+    """
+    uwlines = self._ParseAndUnwrap(code)
+    self.assertEqual(line_joiner.CanMergeMultipleLines(uwlines),
+                     join_lines)
+
+  def testSimpleSingleLineStatement(self):
+    code = textwrap.dedent(u"""\
+        if isinstance(a, int): continue
+        """)
+    self._CheckLineJoining(code, join_lines=True)
+
+  def testSimpleMultipleLineStatement(self):
+    code = textwrap.dedent(u"""\
+        if isinstance(b, int):
+            continue
+        """)
+    self._CheckLineJoining(code, join_lines=False)
+
+  def testSimpleMultipleLineComplexStatement(self):
+    code = textwrap.dedent(u"""\
+        if isinstance(c, int):
+            while True:
+                continue
+        """)
+    self._CheckLineJoining(code, join_lines=False)
+
+  def testSimpleMultipleLineStatementWithComment(self):
+    code = textwrap.dedent(u"""\
+        if isinstance(d, int): continue  # We're pleased that d's an int.
+        """)
+    self._CheckLineJoining(code, join_lines=True)
+
+  def testSimpleMultipleLineStatementWithLargeIndent(self):
+    code = textwrap.dedent(u"""\
+        if isinstance(e, int):    continue
+        """)
+    self._CheckLineJoining(code, join_lines=True)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(LineJoinerTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/pytree_unwrapper_test.py b/yapftests/pytree_unwrapper_test.py
new file mode 100644
index 0000000..abc2ffc
--- /dev/null
+++ b/yapftests/pytree_unwrapper_test.py
@@ -0,0 +1,378 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.pytree_unwrapper."""
+
+import sys
+import textwrap
+import unittest
+
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+
+
+class PytreeUnwrapperTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code, dumptree=False):
+    """Produces unwrapped lines from the given code.
+
+    Parses the code into a tree, performs comment splicing and runs the
+    unwrapper.
+
+    Arguments:
+      code: code to parse as a string
+      dumptree: if True, the parsed pytree (after comment splicing) is dumped
+        to stderr. Useful for debugging.
+
+    Returns:
+      List of unwrapped lines.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    if dumptree:
+      pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+    return pytree_unwrapper.UnwrapPyTree(tree)
+
+  def _CheckUnwrappedLines(self, uwlines, list_of_expected):
+    """Check that the given UnwrappedLines match expectations.
+
+    Args:
+      uwlines: list of UnwrappedLine
+      list_of_expected: list of (depth, values) pairs. Non-semantic tokens are
+        filtered out from the expected values.
+    """
+    actual = []
+    for uwl in uwlines:
+      filtered_values = [ft.value
+                         for ft in uwl.tokens
+                         if ft.name not in pytree_utils.NONSEMANTIC_TOKENS]
+      actual.append((uwl.depth, filtered_values))
+
+    self.assertEqual(list_of_expected, actual)
+
+  def testSimpleFileScope(self):
+    code = textwrap.dedent(r"""
+      x = 1
+      # a comment
+      y = 2
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['x', '=', '1']),
+        (0, ['# a comment']),
+        (0, ['y', '=', '2'])])
+
+  def testSimpleMultilineStatement(self):
+    code = textwrap.dedent(r"""
+      y = (1 +
+           x)
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['y', '=', '(', '1', '+', 'x', ')'])])
+
+  def testFileScopeWithInlineComment(self):
+    code = textwrap.dedent(r"""
+      x = 1    # a comment
+      y = 2
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['x', '=', '1', '# a comment']),
+        (0, ['y', '=', '2'])])
+
+  def testSimpleIf(self):
+    code = textwrap.dedent(r"""
+      if foo:
+          x = 1
+          y = 2
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['if', 'foo', ':']),
+        (1, ['x', '=', '1']),
+        (1, ['y', '=', '2'])])
+
+  def testSimpleIfWithComments(self):
+    code = textwrap.dedent(r"""
+      # c1
+      if foo: # c2
+          x = 1
+          y = 2
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['# c1']),
+        (0, ['if', 'foo', ':', '# c2']),
+        (1, ['x', '=', '1']),
+        (1, ['y', '=', '2'])])
+
+  def testIfWithCommentsInside(self):
+    code = textwrap.dedent(r"""
+      if foo:
+          # c1
+          x = 1 # c2
+          # c3
+          y = 2
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['if', 'foo', ':']),
+        (1, ['# c1']),
+        (1, ['x', '=', '1', '# c2']),
+        (1, ['# c3']),
+        (1, ['y', '=', '2'])])
+
+  def testIfElifElse(self):
+    code = textwrap.dedent(r"""
+       if x:
+         x = 1 # c1
+       elif y: # c2
+         y = 1
+       else:
+         # c3
+         z = 1
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['if', 'x', ':']),
+        (1, ['x', '=', '1', '# c1']),
+        (0, ['elif', 'y', ':', '# c2']),
+        (1, ['y', '=', '1']),
+        (0, ['else', ':']),
+        (1, ['# c3']),
+        (1, ['z', '=', '1'])])
+
+  def testNestedCompoundTwoLevel(self):
+    code = textwrap.dedent(r"""
+       if x:
+         x = 1 # c1
+         while t:
+           # c2
+           j = 1
+         k = 1
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['if', 'x', ':']),
+        (1, ['x', '=', '1', '# c1']),
+        (1, ['while', 't', ':']),
+        (2, ['# c2']),
+        (2, ['j', '=', '1']),
+        (1, ['k', '=', '1'])])
+
+  def testSimpleWhile(self):
+    code = textwrap.dedent(r"""
+       while x > 1: # c1
+          # c2
+          x = 1
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['while', 'x', '>', '1', ':', '# c1']),
+        (1, ['# c2']),
+        (1, ['x', '=', '1'])])
+
+  def testSimpleTry(self):
+    code = textwrap.dedent(r"""
+      try:
+        pass
+      except:
+        pass
+      except:
+        pass
+      else:
+        pass
+      finally:
+        pass
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['try', ':']),
+        (1, ['pass']),
+        (0, ['except', ':']),
+        (1, ['pass']),
+        (0, ['except', ':']),
+        (1, ['pass']),
+        (0, ['else', ':']),
+        (1, ['pass']),
+        (0, ['finally', ':']),
+        (1, ['pass'])])
+
+  def testSimpleFuncdef(self):
+    code = textwrap.dedent(r"""
+      def foo(x): # c1
+        # c2
+        return x
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['def', 'foo', '(', 'x', ')', ':', '# c1']),
+        (1, ['# c2']),
+        (1, ['return', 'x'])])
+
+  def testTwoFuncDefs(self):
+    code = textwrap.dedent(r"""
+      def foo(x): # c1
+        # c2
+        return x
+
+      def bar(): # c3
+        # c4
+        return x
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['def', 'foo', '(', 'x', ')', ':', '# c1']),
+        (1, ['# c2']),
+        (1, ['return', 'x']),
+        (0, ['def', 'bar', '(', ')', ':', '# c3']),
+        (1, ['# c4']),
+        (1, ['return', 'x'])])
+
+  def testSimpleClassDef(self):
+    code = textwrap.dedent(r"""
+      class Klass: # c1
+        # c2
+        p = 1
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['class', 'Klass', ':', '# c1']),
+        (1, ['# c2']),
+        (1, ['p', '=', '1'])])
+
+  def testSingleLineStmtInFunc(self):
+    code = textwrap.dedent(r"""
+        def f(): return 37
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['def', 'f', '(', ')', ':']),
+        (1, ['return', '37'])])
+
+  def testMultipleComments(self):
+    code = textwrap.dedent(r"""
+        # Comment #1
+
+        # Comment #2
+        def f():
+          pass
+      """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckUnwrappedLines(uwlines, [
+        (0, ['# Comment #1']),
+        (0, ['# Comment #2']),
+        (0, ['def', 'f', '(', ')', ':']),
+        (1, ['pass'])])
+
+
+class MatchBracketsTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code, dumptree=False):
+    """Produces unwrapped lines from the given code.
+
+    Parses the code into a tree, match brackets and runs the unwrapper.
+
+    Arguments:
+      code: code to parse as a string
+      dumptree: if True, the parsed pytree (after comment splicing) is dumped to
+        stderr. Useful for debugging.
+
+    Returns:
+      List of unwrapped lines.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+
+    if dumptree:
+      pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+    return pytree_unwrapper.UnwrapPyTree(tree)
+
+  def _CheckMatchingBrackets(self, uwlines, list_of_expected):
+    """Check that the tokens have the expected matching bracket.
+
+    Arguments:
+      uwlines: list of UnwrappedLine.
+      list_of_expected: list of (index, index) pairs. The matching brackets at
+        the indexes need to match. Non-semantic tokens are filtered out from the
+        expected values.
+    """
+    actual = []
+    for uwl in uwlines:
+      filtered_values = [(ft, ft.matching_bracket)
+                         for ft in uwl.tokens
+                         if ft.name not in pytree_utils.NONSEMANTIC_TOKENS]
+      if filtered_values:
+        actual.append(filtered_values)
+
+    for index, bracket_list in enumerate(list_of_expected):
+      uwline = actual[index]
+      if not bracket_list:
+        for value in uwline:
+          self.assertIsNone(value[1])
+      else:
+        for open_bracket, close_bracket in bracket_list:
+          self.assertEqual(uwline[open_bracket][0], uwline[close_bracket][1])
+          self.assertEqual(uwline[close_bracket][0], uwline[open_bracket][1])
+
+  def testFunctionDef(self):
+    code = textwrap.dedent("""\
+        def foo(a, b={'hello': ['w','d']}, c=[42, 37]):
+          pass
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckMatchingBrackets(uwlines, [
+        [(2, 24), (7, 15), (10, 14), (19, 23)],
+        []
+    ])
+
+  def testDecorator(self):
+    code = textwrap.dedent("""\
+        @bar()
+        def foo(a, b, c):
+          pass
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckMatchingBrackets(uwlines, [
+        [(2, 3)],
+        [(2, 8)],
+        []
+    ])
+
+  def testClassDef(self):
+    code = textwrap.dedent("""\
+        class A(B, C, D):
+          pass
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckMatchingBrackets(uwlines, [
+        [(2, 8)],
+        []
+    ])
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(PytreeUnwrapperTest))
+  result.addTests(unittest.makeSuite(MatchBracketsTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/pytree_utils_test.py b/yapftests/pytree_utils_test.py
new file mode 100644
index 0000000..63fa710
--- /dev/null
+++ b/yapftests/pytree_utils_test.py
@@ -0,0 +1,194 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.pytree_utils."""
+
+import unittest
+
+from lib2to3 import pygram
+from lib2to3 import pytree
+from lib2to3.pgen2 import token
+
+from yapf.yapflib import pytree_utils
+
+# More direct access to the symbol->number mapping living within the grammar
+# module.
+_GRAMMAR_SYMBOL2NUMBER = pygram.python_grammar.symbol2number
+
+_FOO = 'foo'
+_FOO1 = 'foo1'
+_FOO2 = 'foo2'
+_FOO3 = 'foo3'
+_FOO4 = 'foo4'
+_FOO5 = 'foo5'
+
+
+class NodeNameTest(unittest.TestCase):
+
+  def testNodeNameForLeaf(self):
+    leaf = pytree.Leaf(token.LPAR, '(')
+    self.assertEqual('LPAR', pytree_utils.NodeName(leaf))
+
+  def testNodeNameForNode(self):
+    leaf = pytree.Leaf(token.LPAR, '(')
+    node = pytree.Node(pygram.python_grammar.symbol2number['suite'], [leaf])
+    self.assertEqual('suite', pytree_utils.NodeName(node))
+
+
+class ParseCodeToTreeTest(unittest.TestCase):
+
+  def testParseCodeToTree(self):
+    # Since ParseCodeToTree is a thin wrapper around underlying lib2to3
+    # functionality, only a sanity test here...
+    tree = pytree_utils.ParseCodeToTree('foo = 2\n')
+    self.assertEqual('file_input', pytree_utils.NodeName(tree))
+    self.assertEqual(2, len(tree.children))
+    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
+
+  def testPrintFunctionToTree(self):
+    tree = pytree_utils.ParseCodeToTree(
+        'print("hello world", file=sys.stderr)\n')
+    self.assertEqual('file_input', pytree_utils.NodeName(tree))
+    self.assertEqual(2, len(tree.children))
+    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
+
+  def testPrintStatementToTree(self):
+    tree = pytree_utils.ParseCodeToTree(
+        'print "hello world"\n')
+    self.assertEqual('file_input', pytree_utils.NodeName(tree))
+    self.assertEqual(2, len(tree.children))
+    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
+
+
+class InsertNodesBeforeAfterTest(unittest.TestCase):
+
+  def _BuildSimpleTree(self):
+    # Builds a simple tree we can play with in the tests.
+    # The tree looks like this:
+    #
+    #   suite:
+    #     LPAR
+    #     LPAR
+    #     simple_stmt:
+    #       NAME('foo')
+    #
+    lpar1 = pytree.Leaf(token.LPAR, '(')
+    lpar2 = pytree.Leaf(token.LPAR, '(')
+    simple_stmt = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
+                              [pytree.Leaf(token.NAME, 'foo')])
+    return pytree.Node(_GRAMMAR_SYMBOL2NUMBER['suite'],
+                       [lpar1, lpar2, simple_stmt])
+
+  def _MakeNewNodeRPAR(self):
+    return pytree.Leaf(token.RPAR, ')')
+
+  def setUp(self):
+    self._simple_tree = self._BuildSimpleTree()
+
+  def testInsertNodesBefore(self):
+    # Insert before simple_stmt and make sure it went to the right place
+    pytree_utils.InsertNodesBefore(
+        [self._MakeNewNodeRPAR()], self._simple_tree.children[2])
+    self.assertEqual(4, len(self._simple_tree.children))
+    self.assertEqual('RPAR',
+                     pytree_utils.NodeName(self._simple_tree.children[2]))
+    self.assertEqual('simple_stmt',
+                     pytree_utils.NodeName(self._simple_tree.children[3]))
+
+  def testInsertNodesBeforeFirstChild(self):
+    # Insert before the first child of its parent
+    simple_stmt = self._simple_tree.children[2]
+    foo_child = simple_stmt.children[0]
+    pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()], foo_child)
+    self.assertEqual(3, len(self._simple_tree.children))
+    self.assertEqual(2, len(simple_stmt.children))
+    self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[0]))
+    self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[1]))
+
+  def testInsertNodesAfter(self):
+    # Insert after and make sure it went to the right place
+    pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()],
+                                  self._simple_tree.children[2])
+    self.assertEqual(4, len(self._simple_tree.children))
+    self.assertEqual('simple_stmt',
+                     pytree_utils.NodeName(self._simple_tree.children[2]))
+    self.assertEqual('RPAR',
+                     pytree_utils.NodeName(self._simple_tree.children[3]))
+
+  def testInsertNodesAfterLastChild(self):
+    # Insert after the last child of its parent
+    simple_stmt = self._simple_tree.children[2]
+    foo_child = simple_stmt.children[0]
+    pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()], foo_child)
+    self.assertEqual(3, len(self._simple_tree.children))
+    self.assertEqual(2, len(simple_stmt.children))
+    self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[0]))
+    self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[1]))
+
+  def testInsertNodesWhichHasParent(self):
+    # Try to insert an existing tree node into another place and fail.
+    with self.assertRaises(RuntimeError):
+      pytree_utils.InsertNodesAfter(
+          [self._simple_tree.children[1]], self._simple_tree.children[0])
+
+
+class AnnotationsTest(unittest.TestCase):
+
+  def setUp(self):
+    self._leaf = pytree.Leaf(token.LPAR, '(')
+    self._node = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
+                             [pytree.Leaf(token.NAME, 'foo')])
+
+  def testGetWhenNone(self):
+    self.assertIsNone(pytree_utils.GetNodeAnnotation(self._leaf, _FOO))
+
+  def testSetWhenNone(self):
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
+
+  def testSetAgain(self):
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 30)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 30)
+
+  def testMultiple(self):
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO1, 1)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO2, 2)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO3, 3)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO4, 4)
+    pytree_utils.SetNodeAnnotation(self._leaf, _FOO5, 5)
+
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO1), 1)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO2), 2)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO3), 3)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO4), 4)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO5), 5)
+
+  def testSetOnNode(self):
+    pytree_utils.SetNodeAnnotation(self._node, _FOO, 20)
+    self.assertEqual(pytree_utils.GetNodeAnnotation(self._node, _FOO), 20)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(NodeNameTest))
+  result.addTests(unittest.makeSuite(ParseCodeToTreeTest))
+  result.addTests(unittest.makeSuite(InsertNodesBeforeAfterTest))
+  result.addTests(unittest.makeSuite(AnnotationsTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/pytree_visitor_test.py b/yapftests/pytree_visitor_test.py
new file mode 100644
index 0000000..c7ec3c5
--- /dev/null
+++ b/yapftests/pytree_visitor_test.py
@@ -0,0 +1,123 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.pytree_visitor."""
+
+import cStringIO
+import unittest
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+
+
+class _NodeNameCollector(pytree_visitor.PyTreeVisitor):
+  """A tree visitor that collects the names of all tree nodes into a list.
+
+  Attributes:
+    all_node_names: collected list of the names, available when the traversal
+      is over.
+    name_node_values: collects a list of NAME leaves (in addition to those going
+      into all_node_names).
+  """
+
+  def __init__(self):
+    self.all_node_names = []
+    self.name_node_values = []
+
+  def DefaultNodeVisit(self, node):
+    self.all_node_names.append(pytree_utils.NodeName(node))
+    super(_NodeNameCollector, self).DefaultNodeVisit(node)
+
+  def DefaultLeafVisit(self, leaf):
+    self.all_node_names.append(pytree_utils.NodeName(leaf))
+
+  def Visit_NAME(self, leaf):
+    self.name_node_values.append(leaf.value)
+    self.DefaultLeafVisit(leaf)
+
+
+_VISITOR_TEST_SIMPLE_CODE = r'''
+foo = bar
+baz = x
+'''
+_VISITOR_TEST_NESTED_CODE = r'''
+if x:
+  if y:
+    return z
+'''
+
+
+class PytreeVisitorTest(unittest.TestCase):
+
+  def testCollectAllNodeNamesSimpleCode(self):
+    tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE)
+    collector = _NodeNameCollector()
+    collector.Visit(tree)
+    expected_names = [
+        'file_input',
+        'simple_stmt', 'expr_stmt', 'NAME', 'EQUAL', 'NAME', 'NEWLINE',
+        'simple_stmt', 'expr_stmt', 'NAME', 'EQUAL', 'NAME', 'NEWLINE',
+        'ENDMARKER']
+    self.assertEqual(expected_names, collector.all_node_names)
+
+    expected_name_node_values = ['foo', 'bar', 'baz', 'x']
+    self.assertEqual(expected_name_node_values, collector.name_node_values)
+
+  def testCollectAllNodeNamesNestedCode(self):
+    tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_NESTED_CODE)
+    collector = _NodeNameCollector()
+    collector.Visit(tree)
+    expected_names = [
+        'file_input',
+        'if_stmt', 'NAME', 'NAME', 'COLON',
+        'suite', 'NEWLINE',
+        'INDENT', 'if_stmt', 'NAME', 'NAME', 'COLON', 'suite', 'NEWLINE',
+        'INDENT', 'simple_stmt', 'return_stmt', 'NAME', 'NAME', 'NEWLINE',
+        'DEDENT', 'DEDENT', 'ENDMARKER']
+    self.assertEqual(expected_names, collector.all_node_names)
+
+    expected_name_node_values = ['if', 'x', 'if', 'y', 'return', 'z']
+    self.assertEqual(expected_name_node_values, collector.name_node_values)
+
+  def testDumper(self):
+    # PyTreeDumper is mainly a debugging utility, so only do basic sanity
+    # checking.
+    tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE)
+    stream = cStringIO.StringIO()
+    pytree_visitor.PyTreeDumper(target_stream=stream).Visit(tree)
+
+    dump_output = stream.getvalue()
+    self.assertIn('file_input [3 children]', dump_output)
+    self.assertIn("NAME(Leaf(1, 'foo'))", dump_output)
+    self.assertIn("EQUAL(Leaf(22, '='))", dump_output)
+
+  def testDumpPyTree(self):
+    # Similar sanity checking for the convenience wrapper DumpPyTree
+    tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE)
+    stream = cStringIO.StringIO()
+    pytree_visitor.DumpPyTree(tree, target_stream=stream)
+
+    dump_output = stream.getvalue()
+    self.assertIn('file_input [3 children]', dump_output)
+    self.assertIn("NAME(Leaf(1, 'foo'))", dump_output)
+    self.assertIn("EQUAL(Leaf(22, '='))", dump_output)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(PytreeVisitorTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/reformatter_test.py b/yapftests/reformatter_test.py
new file mode 100644
index 0000000..3df601d
--- /dev/null
+++ b/yapftests/reformatter_test.py
@@ -0,0 +1,1249 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.reformatter."""
+
+import sys
+import textwrap
+import unittest
+
+from yapf.yapflib import blank_line_calculator
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import reformatter
+from yapf.yapflib import split_penalty
+from yapf.yapflib import subtype_assigner
+
+
+class SingleLineReformatterTest(unittest.TestCase):
+
+  def testSimple(self):
+    unformatted_code = textwrap.dedent("""\
+        if a+b:
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if a + b:
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testSimpleFunctions(self):
+    unformatted_code = textwrap.dedent("""\
+        def g():
+          pass
+
+        def f():
+          pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def g():
+          pass
+
+
+        def f():
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testSimpleFunctionsWithTrailingComments(self):
+    unformatted_code = textwrap.dedent("""\
+        def g():  # Trailing comment
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def f(  # Intermediate comment
+        ):
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def g():  # Trailing comment
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+
+        def f(  # Intermediate comment
+        ):
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testLineContinuation(self):
+    unformatted_code = textwrap.dedent("""\
+        x = {  'a':37,'b':42,
+
+        'c':927}
+
+        y = 'hello ''world'
+        z = 'hello '+'world'
+        a = 'hello {}'.format('world')
+        class foo  (     object  ):
+          def f    (self   ):
+            return       \\
+        37*-+2
+          def g(self, x,y=42):
+              return y
+        def f  (   a ) :
+          return      37+-+a[42-x :  y**3]
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        x = {'a': 37, 'b': 42, 'c': 927}
+
+        y = 'hello ' 'world'
+        z = 'hello ' + 'world'
+        a = 'hello {}'.format('world')
+
+
+        class foo(object):
+
+          def f(self):
+            return 37 * -+2
+
+          def g(self, x, y=42):
+            return y
+
+
+        def f(a):
+          return 37 + -+a[42 - x:y ** 3]
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testComments(self):
+    unformatted_code = textwrap.dedent("""\
+        class Foo(object):
+          pass
+        # End class Foo
+
+        # Attached comment
+        class Bar(object):
+          pass
+
+        # Intermediate comment
+
+        class Qux(object):
+          pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        class Foo(object):
+          pass
+        # End class Foo
+
+
+        # Attached comment
+        class Bar(object):
+          pass
+
+        # Intermediate comment
+
+
+        class Qux(object):
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testDocstrings(self):
+    unformatted_code = textwrap.dedent('''\
+        u"""Module-level docstring."""
+        import os
+        class Foo(object):
+
+          """Class-level docstring."""
+          # A comment for qux.
+          def qux(self):
+
+
+            """Function-level docstring.
+
+            A multiline function docstring.
+            """
+            print('hello {}'.format('world'))
+            return 42
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        u"""Module-level docstring."""
+        import os
+
+
+        class Foo(object):
+          """Class-level docstring."""
+
+          # A comment for qux.
+          def qux(self):
+            """Function-level docstring.
+
+            A multiline function docstring.
+            """
+            print('hello {}'.format('world'))
+            return 42
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testDocstringAndMultilineComment(self):
+    unformatted_code = textwrap.dedent('''\
+        """Hello world"""
+        # A multiline
+        # comment
+        class bar(object):
+          """class docstring"""
+          # class multiline
+          # comment
+          def foo(self):
+            """Another docstring."""
+            # Another multiline
+            # comment
+            pass
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        """Hello world"""
+
+
+        # A multiline
+        # comment
+        class bar(object):
+          """class docstring"""
+
+          # class multiline
+          # comment
+          def foo(self):
+            """Another docstring."""
+            # Another multiline
+            # comment
+            pass
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testMultilineDocstringAndMultilineComment(self):
+    unformatted_code = textwrap.dedent('''\
+        """Hello world
+
+        RIP Dennis Richie.
+        """
+        # A multiline
+        # comment
+        class bar(object):
+          """class docstring
+
+          A classy class.
+          """
+          # class multiline
+          # comment
+          def foo(self):
+            """Another docstring.
+
+            A functional function.
+            """
+            # Another multiline
+            # comment
+            pass
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        """Hello world
+
+        RIP Dennis Richie.
+        """
+
+
+        # A multiline
+        # comment
+        class bar(object):
+          """class docstring
+
+          A classy class.
+          """
+
+          # class multiline
+          # comment
+          def foo(self):
+            """Another docstring.
+
+            A functional function.
+            """
+            # Another multiline
+            # comment
+            pass
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testTupleCommaBeforeLastParen(self):
+    unformatted_code = textwrap.dedent("""\
+        a = ( 1, )
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        a = (1,)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testNoBreakOutsideOfBracket(self):
+    # FIXME(morbo): How this is formatted is not correct. But it's syntactically
+    # correct.
+    unformatted_code = textwrap.dedent("""\
+        def f():
+          assert port >= minimum, \
+'Unexpected port %d when minimum was %d.' % (port, minimum)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def f():
+          assert port >= minimum, 'Unexpected port %d when minimum was %d.' % (port,
+                                                                               minimum)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testBlankLinesBeforeDecorators(self):
+    unformatted_code = textwrap.dedent("""\
+        @foo()
+        class A(object):
+          @bar()
+          @baz()
+          def x(self):
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        @foo()
+        class A(object):
+
+          @bar()
+          @baz()
+          def x(self):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testOpeningAndClosingBrackets(self):
+    unformatted_code = textwrap.dedent("""\
+        foo( ( 1, 2, 3, ) )
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        foo((1, 2, 3,))
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testSingleLineFunctions(self):
+    unformatted_code = textwrap.dedent("""\
+        def foo():  return 42
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def foo():
+          return 42
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testNoQueueSeletionInMiddleOfLine(self):
+    # If the queue isn't properly consttructed, then a token in the middle of
+    # the line may be selected as the one with least penalty. The tokens after
+    # that one are then splatted at the end of the line with no formatting.
+    # FIXME(morbo): The formatting here isn't ideal.
+    unformatted_code = textwrap.dedent("""\
+        find_symbol(node.type) + "< " + " ".join(find_pattern(n) for n in \
+node.child) + " >"
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        find_symbol(node.type) + "< " + " ".join(find_pattern(n)
+                                                 for n in node.child) + " >"
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testNoSpacesBetweenSubscriptsAndCalls(self):
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc() [42] (a, 2)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc()[42](a, 2)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testNoSpacesBetweenOpeningBracketAndStartingOperator(self):
+    # Unary operator.
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc[ -1 ]( -42 )
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc[-1](-42)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    # Varargs and kwargs.
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc( *varargs )
+        aaaaaaaaaa = bbbbbbbb.ccccccccc( **kwargs )
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaa = bbbbbbbb.ccccccccc(*varargs)
+        aaaaaaaaaa = bbbbbbbb.ccccccccc(**kwargs)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testMultilineCommentReformatted(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+            # This is a multiline
+            # comment.
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          # This is a multiline
+          # comment.
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testDictionaryMakerFormatting(self):
+    unformatted_code = textwrap.dedent("""\
+        _PYTHON_STATEMENTS = frozenset({
+            lambda x, y: 'simple_stmt': 'small_stmt', 'expr_stmt': 'print_stmt', 'del_stmt':
+            'pass_stmt', lambda: 'break_stmt': 'continue_stmt', 'return_stmt': 'raise_stmt',
+            'yield_stmt': 'import_stmt', lambda: 'global_stmt': 'exec_stmt', 'assert_stmt':
+            'if_stmt', 'while_stmt': 'for_stmt',
+        })
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        _PYTHON_STATEMENTS = frozenset({
+            lambda x, y: 'simple_stmt': 'small_stmt',
+            'expr_stmt': 'print_stmt',
+            'del_stmt': 'pass_stmt',
+            lambda: 'break_stmt': 'continue_stmt',
+            'return_stmt': 'raise_stmt',
+            'yield_stmt': 'import_stmt',
+            lambda: 'global_stmt': 'exec_stmt',
+            'assert_stmt': 'if_stmt',
+            'while_stmt': 'for_stmt',
+        })
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testSimpleMultilineCode(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+          aaaaaaaaaaaaaa.bbbbbbbbbbbbbb.ccccccc(zzzzzzzzzzzz, \
+xxxxxxxxxxx, yyyyyyyyyyyy, vvvvvvvvv)
+          aaaaaaaaaaaaaa.bbbbbbbbbbbbbb.ccccccc(zzzzzzzzzzzz, \
+xxxxxxxxxxx, yyyyyyyyyyyy, vvvvvvvvv)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          aaaaaaaaaaaaaa.bbbbbbbbbbbbbb.ccccccc(zzzzzzzzzzzz, xxxxxxxxxxx, yyyyyyyyyyyy,
+                                                vvvvvvvvv)
+          aaaaaaaaaaaaaa.bbbbbbbbbbbbbb.ccccccc(zzzzzzzzzzzz, xxxxxxxxxxx, yyyyyyyyyyyy,
+                                                vvvvvvvvv)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testMultilineComment(self):
+    code = textwrap.dedent("""\
+        if Foo:
+          # Hello world
+          # Yo man.
+          # Yo man.
+          # Yo man.
+          # Yo man.
+          a = 42
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testMultilineString(self):
+    code = textwrap.dedent("""\
+        code = textwrap.dedent('''\
+            if Foo:
+              # Hello world
+              # Yo man.
+              # Yo man.
+              # Yo man.
+              # Yo man.
+              a = 42
+            ''')
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent('''\
+        def f():
+            email_text += """<html>This is a really long docstring that goes over the column limit and is multi-line.<br><br>
+        <b>Czar: </b>"""+despot["Nicholas"]+"""<br>
+        <b>Minion: </b>"""+serf["Dmitri"]+"""<br>
+        <b>Residence: </b>"""+palace["Winter"]+"""<br>
+        </body>
+        </html>"""
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        def f():
+          email_text += """<html>This is a really long docstring that goes over the column limit and is multi-line.<br><br>
+        <b>Czar: </b>""" + despot["Nicholas"] + """<br>
+        <b>Minion: </b>""" + serf["Dmitri"] + """<br>
+        <b>Residence: </b>""" + palace["Winter"] + """<br>
+        </body>
+        </html>"""
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testSimpleMultilineWithComments(self):
+    code = textwrap.dedent("""\
+        if (  # This is the first comment
+            a and  # This is the second comment
+            # This is the third comment
+            b):  # A trailing comment
+          # Whoa! A normal comment!!
+          pass  # Another trailing comment
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testMatchingParenSplittingMatching(self):
+    unformatted_code = textwrap.dedent("""\
+        def f():
+          raise RuntimeError('unable to find insertion point for target node',
+                             (target,))
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def f():
+          raise RuntimeError('unable to find insertion point for target node',
+                             (target,))
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testContinuationIndent(self):
+    unformatted_code = textwrap.dedent('''\
+        class F:
+          def _ProcessArgLists(self, node):
+            """Common method for processing argument lists."""
+            for child in node.children:
+              if isinstance(child, pytree.Leaf):
+                self._SetTokenSubtype(
+                    child, subtype=_ARGLIST_TOKEN_TO_SUBTYPE.get(
+                        child.value, format_token.Subtype.NONE))
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        class F:
+
+          def _ProcessArgLists(self, node):
+            """Common method for processing argument lists."""
+            for child in node.children:
+              if isinstance(child, pytree.Leaf):
+                self._SetTokenSubtype(child,
+                                      subtype=_ARGLIST_TOKEN_TO_SUBTYPE.get(
+                                          child.value, \
+format_token.Subtype.NONE))
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testTrailingCommaAndBracket(self):
+    unformatted_code = textwrap.dedent('''\
+        a = { 42, }
+        b = ( 42, )
+        c = [ 42, ]
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        a = {42,}
+        b = (42,)
+        c = [42,]
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testI18n(self):
+    code = textwrap.dedent("""\
+        N_('Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world.')  # A comment is here.
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+    code = textwrap.dedent("""\
+        foo('Fake function call')  #. Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world.
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testClosingBracketIndent(self):
+    unformatted_code = textwrap.dedent('''\
+        def f():
+          def g():
+            while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and
+                   xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) ==
+                   'bbbbbbb'):
+              pass
+        ''')
+    expected_formatted_code = textwrap.dedent('''\
+        def f():
+
+          def g():
+            while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and
+                   xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) ==
+                   'bbbbbbb'):
+              pass
+        ''')
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testClosingBracketsInlinedInCall(self):
+    unformatted_code = textwrap.dedent("""\
+        class Foo(object):
+
+          def bar(self):
+            self.aaaaaaaa = xxxxxxxxxxxxxxxxxxx.yyyyyyyyyyyyy(
+                self.cccccc.ddddddddd.eeeeeeee,
+                options={
+                    "forkforkfork": 1,
+                    "borkborkbork": 2,
+                    "corkcorkcork": 3,
+                    "horkhorkhork": 4,
+                    "porkporkpork": 5,
+                    })
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        class Foo(object):
+
+          def bar(self):
+            self.aaaaaaaa = xxxxxxxxxxxxxxxxxxx.yyyyyyyyyyyyy(
+                self.cccccc.ddddddddd.eeeeeeee,
+                options={
+                    "forkforkfork": 1,
+                    "borkborkbork": 2,
+                    "corkcorkcork": 3,
+                    "horkhorkhork": 4,
+                    "porkporkpork": 5,
+                })
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testLineWrapInForExpression(self):
+    code = textwrap.dedent("""\
+        class A:
+
+          def x(self, node, name, n=1):
+            for i, child in enumerate(itertools.ifilter(
+                lambda c: pytree_utils.NodeName(c) == name, node.pre_order())):
+              pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testFunctionCallContinuationLine(self):
+    code = textwrap.dedent("""\
+        class foo:
+
+          def bar(self, node, name, n=1):
+            if True:
+              if True:
+                return [(aaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(
+                    cccc, ddddddddddddddddddddddddddddddddddddd))]
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testI18nNonFormatting(self):
+    code = textwrap.dedent("""\
+        class F(object):
+
+          def __init__(self, fieldname,
+                       #. Error message indicating an invalid e-mail address.
+                       message=N_('Please check your email address.'), **kwargs):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testNoSpaceBetweenUnaryOpAndOpeningParen(self):
+    code = textwrap.dedent("""\
+        if ~(a or b):
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testCommentBeforeFuncDef(self):
+    code = textwrap.dedent("""\
+        class Foo(object):
+
+          a = 42
+
+          # This is a comment.
+          def __init__(self, xxxxxxx,
+                       yyyyy=0,
+                       zzzzzzz=None,
+                       aaaaaaaaaaaaaaaaaa=False,
+                       bbbbbbbbbbbbbbb=False):
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testExcessLineCountWithDefaultKeywords(self):
+    unformatted_code = textwrap.dedent("""\
+        class Fnord(object):
+          def Moo(self):
+            aaaaaaaaaaaaaaaa = self._bbbbbbbbbbbbbbbbbbbbbbb(
+                ccccccccccccc=ccccccccccccc, ddddddd=ddddddd, eeee=eeee,
+                fffff=fffff, ggggggg=ggggggg, hhhhhhhhhhhhh=hhhhhhhhhhhhh,
+                iiiiiii=iiiiiiiiiiiiii)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        class Fnord(object):
+
+          def Moo(self):
+            aaaaaaaaaaaaaaaa = self._bbbbbbbbbbbbbbbbbbbbbbb(
+                ccccccccccccc=ccccccccccccc,
+                ddddddd=ddddddd,
+                eeee=eeee,
+                fffff=fffff,
+                ggggggg=ggggggg,
+                hhhhhhhhhhhhh=hhhhhhhhhhhhh,
+                iiiiiii=iiiiiiiiiiiiii)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+
+class BuganizerFixes(unittest.TestCase):
+
+  def testB19377034(self):
+    code = textwrap.dedent("""\
+        def f():
+          if (aaaaaaaaaaaaaaa.start >= aaaaaaaaaaaaaaa.end or
+              bbbbbbbbbbbbbbb.start >= bbbbbbbbbbbbbbb.end):
+            return False
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB19372573(self):
+    code = textwrap.dedent("""\
+        def f():
+          if a: return 42
+          while True:
+            if b: continue
+            if c: break
+          return 0
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB19353268(self):
+    code = textwrap.dedent("""\
+        a = {1, 2, 3}[x]
+        b = {'foo': 42, 'bar': 37}['foo']
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB19287512(self):
+    unformatted_code = textwrap.dedent("""\
+        class Foo(object):
+
+          def bar(self):
+            with xxxxxxxxxx.yyyyy(
+                'aaaaaaa.bbbbbbbb.ccccccc.dddddddddddddddddddd.eeeeeeeeeee',
+                fffffffffff=(aaaaaaa.bbbbbbbb.ccccccc.dddddddddddddddddddd
+                             .Mmmmmmmmmmmmmmmmmm(-1, 'permission error'))):
+              self.assertRaises(nnnnnnnnnnnnnnnn.ooooo, ppppp.qqqqqqqqqqqqqqqqq)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        class Foo(object):
+
+          def bar(self):
+            with xxxxxxxxxx.yyyyy(
+                'aaaaaaa.bbbbbbbb.ccccccc.dddddddddddddddddddd.eeeeeeeeeee',
+                fffffffffff=(
+                    aaaaaaa.bbbbbbbb.ccccccc.dddddddddddddddddddd.Mmmmmmmmmmmmmmmmmm(
+                        -1, 'permission error')
+                )):
+              self.assertRaises(nnnnnnnnnnnnnnnn.ooooo, ppppp.qqqqqqqqqqqqqqqqq)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB19194420(self):
+    unformatted_code = textwrap.dedent("""\
+        method.Set(
+            'long argument goes here that causes the line to break',
+            lambda arg2=0.5: arg2)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        method.Set('long argument goes here that causes the line to break',
+                   lambda arg2=0.5: arg2)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB19073499(self):
+    code = textwrap.dedent("""\
+        instance = (aaaaaaa.bbbbbbb().ccccccccccccccccc().ddddddddddd(
+            {'aa': 'context!'}).eeeeeeeeeeeeeeeeeee(
+            {  # Inline comment about why fnord has the value 6.
+                'fnord': 6
+            }))
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB18257115(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+          if True:
+             self._Test(
+                 aaaa, bbbbbbb.cccccccccc, dddddddd, eeeeeeeeeee,
+                 [ffff, ggggggggggg, hhhhhhhhhhhh, iiiiii, jjjj])
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          if True:
+            self._Test(aaaa, bbbbbbb.cccccccccc, dddddddd, eeeeeeeeeee,
+                       [ffff, ggggggggggg, hhhhhhhhhhhh, iiiiii, jjjj])
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB18256666(self):
+    code = textwrap.dedent("""\
+        class Foo(object):
+
+          def Bar(self):
+            aaaaa.bbbbbbb(ccc='ddddddddddddddd',
+                          eeee='ffffffffffffffffffffff-%s-%s' % (gggg,
+                                                                 int(time.time())),
+                          hhhhhh={
+                              'iiiiiiiiiii': iiiiiiiiiii,
+                              'jjjj': jjjj.jjjjj(),
+                              'kkkkkkkkkkkk': kkkkkkkkkkkk,
+                          },
+                          llllllllll=mmmmmm.nnnnnnnnnnnnnnnn)
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB18256826(self):
+    code = textwrap.dedent("""\
+        if True:
+          pass
+        # A multiline comment.
+        # Line two.
+        elif False:
+          pass
+
+        if True:
+          pass
+          # A multiline comment.
+          # Line two.
+        elif False:
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB18255697(self):
+    code = textwrap.dedent("""\
+        AAAAAAAAAAAAAAA = {
+            'XXXXXXXXXXXXXX': 4242,  # Inline comment
+            # Next comment
+            'YYYYYYYYYYYYYYYY': ['zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'],
+        }
+        """)
+    uwlines = _ParseAndUnwrap(code)
+    self.assertEqual(code, reformatter.Reformat(uwlines))
+
+  def testB17534869(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+          self.assertLess(abs(time.time()-aaaa.bbbbbbbbbbb(
+                              datetime.datetime.now())), 1)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          self.assertLess(abs(time.time() - aaaa.bbbbbbbbbbb(datetime.datetime.now())),
+                          1)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB17489866(self):
+    unformatted_code = textwrap.dedent("""\
+        def f():
+          if True:
+            if True:
+              return aaaa.bbbbbbbbb(ccccccc=dddddddddddddd({('eeee', \
+'ffffffff'): str(j)}))
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def f():
+          if True:
+            if True:
+              return aaaa.bbbbbbbbb(
+                  ccccccc=dddddddddddddd({('eeee', 'ffffffff'): str(j)}))
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB17133019(self):
+    unformatted_code = textwrap.dedent("""\
+        class aaaaaaaaaaaaaa(object):
+
+          def bbbbbbbbbb(self):
+            with io.open("/dev/null", "rb"):
+              with io.open(os.path.join(aaaaa.bbbbb.ccccccccccc,
+                                        DDDDDDDDDDDDDDD,
+                                        "eeeeeeeee ffffffffff",
+                                       ), "rb") as gggggggggggggggggggg:
+                print gggggggggggggggggggg
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        class aaaaaaaaaaaaaa(object):
+
+          def bbbbbbbbbb(self):
+            with io.open("/dev/null", "rb"):
+              with io.open(os.path.join(aaaaa.bbbbb.ccccccccccc, DDDDDDDDDDDDDDD,
+                                        "eeeeeeeee ffffffffff",),
+                           "rb") as gggggggggggggggggggg:
+                print gggggggggggggggggggg
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB17011869(self):
+    unformatted_code = textwrap.dedent("""\
+        '''blah......'''
+
+        class SomeClass(object):
+          '''blah.'''
+
+          AAAAAAAAAAAA = {                        # Comment.
+              'BBB': 1.0,
+                'DDDDDDDD': 0.4811
+                                      }
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        '''blah......'''
+
+
+        class SomeClass(object):
+          '''blah.'''
+
+          AAAAAAAAAAAA = {  # Comment.
+              'BBB': 1.0,
+              'DDDDDDDD': 0.4811
+          }
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB16783631(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+          with aaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccc(ddddddddddddd,
+                                                      eeeeeeeee=self.fffffffffffff
+                                                      )as gggg:
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          with aaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccc(
+              ddddddddddddd,
+              eeeeeeeee=self.fffffffffffff) as gggg:
+            pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB16572361(self):
+    unformatted_code = textwrap.dedent("""\
+        def foo(self):
+         def bar(my_dict_name):
+           self.my_dict_name['foo-bar-baz-biz-boo-baa-baa'].\
+IncrementBy.assert_called_once_with('foo_bar_baz_boo')
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def foo(self):
+
+          def bar(my_dict_name):
+            self.my_dict_name['foo-bar-baz-biz-boo-baa-baa'].\
+IncrementBy.assert_called_once_with(
+                'foo_bar_baz_boo')
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB15884241(self):
+    unformatted_code = textwrap.dedent("""\
+        if 1:
+          if 1:
+            for row in AAAA:
+              self.create(aaaaaaaa="/aaa/bbbb/cccc/dddddd/eeeeeeeeeeeeeeeeeeeeeeeeee/%s" % row [0].replace(".foo", ".bar"), aaaaa=bbb[1], ccccc=bbb[2], dddd=bbb[3], eeeeeeeeeee=[s.strip() for s in bbb[4].split(",")], ffffffff=[s.strip() for s in bbb[5].split(",")], gggggg=bbb[6])
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if 1:
+          if 1:
+            for row in AAAA:
+              self.create(aaaaaaaa="/aaa/bbbb/cccc/dddddd/eeeeeeeeeeeeeeeeeeeeeeeeee/%s"
+                          % row[0].replace(".foo", ".bar"),
+                          aaaaa=bbb[1],
+                          ccccc=bbb[2],
+                          dddd=bbb[3],
+                          eeeeeeeeeee=[s.strip() for s in bbb[4].split(",")],
+                          ffffffff=[s.strip() for s in bbb[5].split(",")],
+                          gggggg=bbb[6])
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB15697268(self):
+    unformatted_code = textwrap.dedent("""\
+        def main(unused_argv):
+          ARBITRARY_CONSTANT_A = 10
+          an_array_with_an_exceedingly_long_name = range(ARBITRARY_CONSTANT_A + 1)
+          ok = an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A]
+          bad_slice = map(math.sqrt, an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A])
+          a_long_name_slicing = an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A]
+          bad_slice = ("I am a crazy, no good, string whats too long, etc." + " no really ")[:ARBITRARY_CONSTANT_A]
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def main(unused_argv):
+          ARBITRARY_CONSTANT_A = 10
+          an_array_with_an_exceedingly_long_name = range(ARBITRARY_CONSTANT_A + 1)
+          ok = an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A]
+          bad_slice = map(math.sqrt,
+                          an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A])
+          a_long_name_slicing = an_array_with_an_exceedingly_long_name[:ARBITRARY_CONSTANT_A]
+          bad_slice = ("I am a crazy, no good, string whats too long, etc." +
+                       " no really ")[:ARBITRARY_CONSTANT_A]
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB15597568(self):
+    unformatted_code = textwrap.dedent("""\
+        if True:
+          if True:
+            if True:
+              print(("Return code was %d" + (", and the process timed out." if did_time_out else ".")) % errorcode)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if True:
+          if True:
+            if True:
+              print(("Return code was %d" + (", and the process timed out." if
+                                             did_time_out else ".")) % errorcode)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB15542157(self):
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaa = bbbb.ccccccccccccccc(dddddd.eeeeeeeeeeeeee, ffffffffffffffffff, gggggg.hhhhhhhhhhhhhhhhh)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaa = bbbb.ccccccccccccccc(dddddd.eeeeeeeeeeeeee, ffffffffffffffffff,
+                                            gggggg.hhhhhhhhhhhhhhhhh)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB15438132(self):
+    unformatted_code = textwrap.dedent("""\
+        if aaaaaaa.bbbbbbbbbb:
+           cccccc.dddddddddd(eeeeeeeeeee=fffffffffffff.gggggggggggggggggg)
+           if hhhhhh.iiiii.jjjjjjjjjjjjj:
+             # This is a comment in the middle of it all.
+             kkkkkkk.llllllllll.mmmmmmmmmmmmm = True
+           if (aaaaaa.bbbbb.ccccccccccccc != ddddddd.eeeeeeeeee.fffffffffffff or
+               eeeeee.fffff.ggggggggggggggggggggggggggg() != hhhhhhh.iiiiiiiiii.jjjjjjjjjjjj):
+             aaaaaaaa.bbbbbbbbbbbb(
+                 aaaaaa.bbbbb.cc,
+                 dddddddddddd=eeeeeeeeeeeeeeeeeee.fffffffffffffffff(
+                     gggggg.hh,
+                     iiiiiiiiiiiiiiiiiii.jjjjjjjjjj.kkkkkkk,
+                     lllll.mm),
+                 nnnnnnnnnn=ooooooo.pppppppppp)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        if aaaaaaa.bbbbbbbbbb:
+          cccccc.dddddddddd(eeeeeeeeeee=fffffffffffff.gggggggggggggggggg)
+          if hhhhhh.iiiii.jjjjjjjjjjjjj:
+            # This is a comment in the middle of it all.
+            kkkkkkk.llllllllll.mmmmmmmmmmmmm = True
+          if (aaaaaa.bbbbb.ccccccccccccc != ddddddd.eeeeeeeeee.fffffffffffff or
+              eeeeee.fffff.ggggggggggggggggggggggggggg() !=
+              hhhhhhh.iiiiiiiiii.jjjjjjjjjjjj):
+            aaaaaaaa.bbbbbbbbbbbb(aaaaaa.bbbbb.cc,
+                                  dddddddddddd=eeeeeeeeeeeeeeeeeee.fffffffffffffffff(
+                                      gggggg.hh, iiiiiiiiiiiiiiiiiii.jjjjjjjjjj.kkkkkkk,
+                                      lllll.mm),
+                                  nnnnnnnnnn=ooooooo.pppppppppp)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB14468247(self):
+    unformatted_code = textwrap.dedent("""\
+        call(a=1,
+            b=2,
+        )
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        call(a=1, b=2,)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB14406499(self):
+    unformatted_code = textwrap.dedent("""\
+        def foo1(parameter_1, parameter_2, parameter_3, parameter_4, \
+parameter_5, parameter_6): pass
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5,
+                 parameter_6):
+          pass
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+  def testB13900309(self):
+    unformatted_code = textwrap.dedent("""\
+        self.aaaaaaaaaaa(  # A comment in the middle of it all.
+               948.0/3600, self.bbb.ccccccccccccccccccccc(dddddddddddddddd.eeee, True))
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        self.aaaaaaaaaaa(  # A comment in the middle of it all.
+            948.0 / 3600, self.bbb.ccccccccccccccccccccc(dddddddddddddddd.eeee, True))
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccccc(
+            DC_1, (CL - 50, CL), AAAAAAAA, BBBBBBBBBBBBBBBB, 98.0,
+            CCCCCCC).ddddddddd(
+                # Look! A comment is here.
+                AAAAAAAA - (20 * 60 - 5))
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccccc(
+            DC_1, (CL - 50, CL), AAAAAAAA, BBBBBBBBBBBBBBBB, 98.0,
+            CCCCCCC).ddddddddd(  # Look! A comment is here.
+            AAAAAAAA - (20 * 60 - 5))
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccccccccccccccccccccc().dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccccccccccccccccccccc(
+        ).dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccccccccccccccccccccc(x).dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbb.ccccccccccccccccccccccccc(
+            x).dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx).dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa(
+            xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx).dddddddddddddddddddddddddd(1, 2, 3, 4)
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+    unformatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa().bbbbbbbbbbbbbbbbbbbbbbbb().ccccccccccccccccccc().\
+dddddddddddddddddd().eeeeeeeeeeeeeeeeeeeee().fffffffffffffffff().gggggggggggggggggg()
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        aaaaaaaaaaaaaaaaaaaaaaaa().bbbbbbbbbbbbbbbbbbbbbbbb().ccccccccccccccccccc(
+        ).dddddddddddddddddd().eeeeeeeeeeeeeeeeeeeee().fffffffffffffffff(
+        ).gggggggggggggggggg()
+        """)
+    uwlines = _ParseAndUnwrap(unformatted_code)
+    self.assertEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
+
+def _ParseAndUnwrap(code, dumptree=False):
+  """Produces unwrapped lines from the given code.
+
+  Parses the code into a tree, performs comment splicing and runs the
+  unwrapper.
+
+  Arguments:
+    code: code to parse as a string
+    dumptree: if True, the parsed pytree (after comment splicing) is dumped
+              to stderr. Useful for debugging.
+
+  Returns:
+    List of unwrapped lines.
+  """
+  tree = pytree_utils.ParseCodeToTree(code)
+  comment_splicer.SpliceComments(tree)
+  subtype_assigner.AssignSubtypes(tree)
+  split_penalty.ComputeSplitPenalties(tree)
+  blank_line_calculator.CalculateBlankLines(tree)
+
+  if dumptree:
+    pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+  uwlines = pytree_unwrapper.UnwrapPyTree(tree)
+  for uwl in uwlines:
+    uwl.CalculateFormattingInformation()
+
+  return uwlines
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(SingleLineReformatterTest))
+  result.addTests(unittest.makeSuite(BuganizerFixes))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/split_penalty_test.py b/yapftests/split_penalty_test.py
new file mode 100644
index 0000000..416b4fa
--- /dev/null
+++ b/yapftests/split_penalty_test.py
@@ -0,0 +1,262 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.split_penalty."""
+
+import sys
+import textwrap
+import unittest
+
+from lib2to3 import pytree
+
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import split_penalty
+
+UNBREAKABLE = split_penalty.UNBREAKABLE
+STRONGLY_CONNECTED = split_penalty.STRONGLY_CONNECTED
+
+
+class SplitPenaltyTest(unittest.TestCase):
+
+  def _ParseAndComputePenalties(self, code, dumptree=False):
+    """Parses the code and computes split penalties.
+
+    Arguments:
+      code: code to parse as a string
+      dumptree: if True, the parsed pytree (after penalty assignment) is dumped
+        to stderr. Useful for debugging.
+
+    Returns:
+      Parse tree.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    split_penalty.ComputeSplitPenalties(tree)
+    if dumptree:
+      pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+    return tree
+
+  def _CheckPenalties(self, tree, list_of_expected):
+    """Check that the tokens in the tree have the correct penalties.
+
+    Args:
+      tree: the pytree.
+      list_of_expected: list of (name, penalty) pairs. Non-semantic tokens are
+        filtered out from the expected values.
+    """
+    def FlattenRec(tree):
+      if pytree_utils.NodeName(tree) in pytree_utils.NONSEMANTIC_TOKENS:
+        return []
+      if isinstance(tree, pytree.Leaf):
+        return [(tree.value,
+                 pytree_utils.GetNodeAnnotation(
+                     tree,
+                     pytree_utils.Annotation.SPLIT_PENALTY))]
+      nodes = []
+      for node in tree.children:
+        nodes += FlattenRec(node)
+      return nodes
+
+    self.assertEqual(list_of_expected, FlattenRec(tree))
+
+  def testUnbreakable(self):
+    # Test function definitions.
+    code = textwrap.dedent(r"""
+      def foo(x):
+        pass
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('def', None),
+        ('foo', UNBREAKABLE),
+        ('(', UNBREAKABLE),
+        ('x', None),
+        (')', None),
+        (':', UNBREAKABLE),
+        ('pass', None),
+    ])
+
+    # Test function definition with trailing comment.
+    code = textwrap.dedent(r"""
+      def foo(x):  # trailing comment
+        pass
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('def', None),
+        ('foo', UNBREAKABLE),
+        ('(', UNBREAKABLE),
+        ('x', None),
+        (')', None),
+        (':', UNBREAKABLE),
+        ('pass', None),
+    ])
+
+    # Test class definitions.
+    code = textwrap.dedent(r"""
+      class A:
+        pass
+      class B(A):
+        pass
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('class', None),
+        ('A', UNBREAKABLE),
+        (':', UNBREAKABLE),
+        ('pass', None),
+        ('class', None),
+        ('B', UNBREAKABLE),
+        ('(', UNBREAKABLE),
+        ('A', None),
+        (')', None),
+        (':', UNBREAKABLE),
+        ('pass', None),
+    ])
+
+    # Test lambda definitions.
+    code = textwrap.dedent(r"""
+      lambda a, b: None
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('lambda', None),
+        ('a', UNBREAKABLE),
+        (',', UNBREAKABLE),
+        ('b', UNBREAKABLE),
+        (':', UNBREAKABLE),
+        ('None', None),
+    ])
+
+    # Test dotted names.
+    code = textwrap.dedent(r"""
+      import a.b.c
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('import', None),
+        ('a', None),
+        ('.', UNBREAKABLE),
+        ('b', UNBREAKABLE),
+        ('.', UNBREAKABLE),
+        ('c', UNBREAKABLE),
+    ])
+
+  def testStronglyConnected(self):
+    # Test dictionary keys.
+    code = textwrap.dedent(r"""
+      a = {
+          'x': 42,
+          y(lambda a: 23): 37,
+      }
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('a', None), ('=', None), ('{', None),
+        ("'x'", STRONGLY_CONNECTED),
+        (':', STRONGLY_CONNECTED),
+        ('42', None),
+        (',', None),
+        ('y', STRONGLY_CONNECTED),
+        ('(', UNBREAKABLE),
+        ('lambda', STRONGLY_CONNECTED),
+        ('a', UNBREAKABLE),
+        (':', UNBREAKABLE),
+        ('23', STRONGLY_CONNECTED),
+        (')', UNBREAKABLE),
+        (':', STRONGLY_CONNECTED),
+        ('37', None),
+        (',', None),
+        ('}', None),
+    ])
+
+    # Test subscripts.
+    code = textwrap.dedent(r"""
+      a[x(42):37:-1]
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('a', None),
+        ('[', UNBREAKABLE),
+        ('x', STRONGLY_CONNECTED),
+        ('(', UNBREAKABLE),
+        ('42', STRONGLY_CONNECTED),
+        (')', UNBREAKABLE),
+        (':', STRONGLY_CONNECTED),
+        ('37', STRONGLY_CONNECTED),
+        (':', STRONGLY_CONNECTED),
+        ('-', STRONGLY_CONNECTED),
+        ('1', STRONGLY_CONNECTED),
+        (']', STRONGLY_CONNECTED),
+    ])
+
+    # Test list comprehension.
+    code = textwrap.dedent(r"""
+      [a for a in foo if a.x == 37]
+      """)
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('[', None),
+        ('a', None),
+        ('for', None),
+        ('a', STRONGLY_CONNECTED),
+        ('in', STRONGLY_CONNECTED),
+        ('foo', STRONGLY_CONNECTED),
+        ('if', None),
+        ('a', STRONGLY_CONNECTED),
+        ('.', UNBREAKABLE),
+        ('x', STRONGLY_CONNECTED),
+        ('==', STRONGLY_CONNECTED),
+        ('37', STRONGLY_CONNECTED),
+        (']', None),
+    ])
+
+  def testFuncCalls(self):
+    code = 'foo(1, 2, 3)\n'
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('foo', None),
+        ('(', UNBREAKABLE),
+        ('1', None),
+        (',', None),
+        ('2', None),
+        (',', None),
+        ('3', None),
+        (')', UNBREAKABLE)])
+
+    # Now a method call, which has more than one trailer
+    code = 'foo.bar.baz(1, 2, 3)\n'
+    tree = self._ParseAndComputePenalties(code)
+    self._CheckPenalties(tree, [
+        ('foo', None),
+        ('.', UNBREAKABLE),
+        ('bar', UNBREAKABLE),
+        ('.', UNBREAKABLE),
+        ('baz', UNBREAKABLE),
+        ('(', UNBREAKABLE),
+        ('1', None),
+        (',', None),
+        ('2', None),
+        (',', None),
+        ('3', None),
+        (')', UNBREAKABLE)])
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(SplitPenaltyTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/subtype_assigner_test.py b/yapftests/subtype_assigner_test.py
new file mode 100644
index 0000000..b1cd342
--- /dev/null
+++ b/yapftests/subtype_assigner_test.py
@@ -0,0 +1,204 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.subtype_assigner."""
+
+import sys
+import textwrap
+import unittest
+
+from yapf.yapflib import format_token
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import pytree_visitor
+from yapf.yapflib import subtype_assigner
+
+
+class SubtypeAssignerTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code, dumptree=False):
+    """Produces unwrapped lines from the given code.
+
+    Parses the code into a tree, assigns subtypes and runs the unwrapper.
+
+    Arguments:
+      code: code to parse as a string
+      dumptree: if True, the parsed pytree (after comment splicing) is dumped
+        to stderr. Useful for debugging.
+
+    Returns:
+      List of unwrapped lines.
+    """
+    tree = pytree_utils.ParseCodeToTree(code)
+    subtype_assigner.AssignSubtypes(tree)
+
+    if dumptree:
+      pytree_visitor.DumpPyTree(tree, target_stream=sys.stderr)
+
+    return pytree_unwrapper.UnwrapPyTree(tree)
+
+  def _CheckFormatTokenSubtypes(self, uwlines, list_of_expected):
+    """Check that the tokens in the UnwrappedLines have the expected subtypes.
+
+    Args:
+      uwlines: list of UnwrappedLine.
+      list_of_expected: list of (name, subtype) pairs. Non-semantic tokens are
+        filtered out from the expected values.
+    """
+    actual = []
+    for uwl in uwlines:
+      filtered_values = [(ft.value, ft.subtype)
+                         for ft in uwl.tokens
+                         if ft.name not in pytree_utils.NONSEMANTIC_TOKENS]
+      if filtered_values:
+        actual.append(filtered_values)
+
+    self.assertEqual(list_of_expected, actual)
+
+  def testFuncDefDefaultAssign(self):
+    code = textwrap.dedent(r"""
+        def foo(a=37, *b, **c):
+          return -x[:42]
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('def', format_token.Subtype.NONE),
+         ('foo', format_token.Subtype.NONE),
+         ('(', format_token.Subtype.NONE),
+         ('a', format_token.Subtype.NONE),
+         ('=', format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN),
+         ('37', format_token.Subtype.NONE),
+         (',', format_token.Subtype.NONE),
+         ('*', format_token.Subtype.VARARGS_STAR),
+         ('b', format_token.Subtype.NONE),
+         (',', format_token.Subtype.NONE),
+         ('**', format_token.Subtype.KWARGS_STAR_STAR),
+         ('c', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         (':', format_token.Subtype.NONE)],
+
+        [('return', format_token.Subtype.NONE),
+         ('-', format_token.Subtype.UNARY_OPERATOR),
+         ('x', format_token.Subtype.NONE),
+         ('[', format_token.Subtype.NONE),
+         (':', format_token.Subtype.SUBSCRIPT_COLON),
+         ('42', format_token.Subtype.NONE),
+         (']', format_token.Subtype.NONE)]
+    ])
+
+  def testFuncCallWithDefaultAssign(self):
+    code = textwrap.dedent(r"""
+        foo(x, a='hello world')
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('foo', format_token.Subtype.NONE),
+         ('(', format_token.Subtype.NONE),
+         ('x', format_token.Subtype.NONE),
+         (',', format_token.Subtype.NONE),
+         ('a', format_token.Subtype.NONE),
+         ('=', format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN),
+         ("'hello world'", format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE)]
+    ])
+
+  def testSetComprehension(self):
+    code = textwrap.dedent("""\
+        def foo(strs):
+          return {s.lower() for s in strs}
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('def', format_token.Subtype.NONE),
+         ('foo', format_token.Subtype.NONE),
+         ('(', format_token.Subtype.NONE),
+         ('strs', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         (':', format_token.Subtype.NONE)],
+
+        [('return', format_token.Subtype.NONE),
+         ('{', format_token.Subtype.NONE),
+         ('s', format_token.Subtype.NONE),
+         ('.', format_token.Subtype.NONE),
+         ('lower', format_token.Subtype.NONE),
+         ('(', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         ('for', format_token.Subtype.DICT_SET_GENERATOR),
+         ('s', format_token.Subtype.NONE),
+         ('in', format_token.Subtype.NONE),
+         ('strs', format_token.Subtype.NONE),
+         ('}', format_token.Subtype.NONE)]
+    ])
+
+  def testUnaryNotOperator(self):
+    code = textwrap.dedent("""\
+        not a
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('not', format_token.Subtype.UNARY_OPERATOR),
+         ('a', format_token.Subtype.NONE)]
+    ])
+
+  def testBitwiseOperators(self):
+    code = textwrap.dedent("""\
+        x = ((a | (b ^ 3) & c) << 3) >> 1
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('x', format_token.Subtype.NONE),
+         ('=', format_token.Subtype.ASSIGN_OPERATOR),
+         ('(', format_token.Subtype.NONE),
+         ('(', format_token.Subtype.NONE),
+         ('a', format_token.Subtype.NONE),
+         ('|', format_token.Subtype.BINARY_OPERATOR),
+         ('(', format_token.Subtype.NONE),
+         ('b', format_token.Subtype.NONE),
+         ('^', format_token.Subtype.BINARY_OPERATOR),
+         ('3', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         ('&', format_token.Subtype.BINARY_OPERATOR),
+         ('c', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         ('<<', format_token.Subtype.BINARY_OPERATOR),
+         ('3', format_token.Subtype.NONE),
+         (')', format_token.Subtype.NONE),
+         ('>>', format_token.Subtype.BINARY_OPERATOR),
+         ('1', format_token.Subtype.NONE)]
+    ])
+
+  def testSubscriptColon(self):
+    code = textwrap.dedent("""\
+        x[0:42:1]
+        """)
+    uwlines = self._ParseAndUnwrap(code)
+    self._CheckFormatTokenSubtypes(uwlines, [
+        [('x', format_token.Subtype.NONE),
+         ('[', format_token.Subtype.NONE),
+         ('0', format_token.Subtype.NONE),
+         (':', format_token.Subtype.SUBSCRIPT_COLON),
+         ('42', format_token.Subtype.NONE),
+         (':', format_token.Subtype.SUBSCRIPT_COLON),
+         ('1', format_token.Subtype.NONE),
+         (']', format_token.Subtype.NONE)]
+    ])
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(SubtypeAssignerTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/unwrapped_line_test.py b/yapftests/unwrapped_line_test.py
new file mode 100644
index 0000000..4013656
--- /dev/null
+++ b/yapftests/unwrapped_line_test.py
@@ -0,0 +1,119 @@
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.unwrapped_line."""
+
+import textwrap
+import unittest
+
+from lib2to3 import pytree
+from lib2to3.pgen2 import token
+
+from yapf.yapflib import comment_splicer
+from yapf.yapflib import format_token
+from yapf.yapflib import pytree_unwrapper
+from yapf.yapflib import pytree_utils
+from yapf.yapflib import split_penalty
+from yapf.yapflib import subtype_assigner
+from yapf.yapflib import unwrapped_line
+
+
+def _MakeFormatTokenLeaf(token_type, token_value):
+  return format_token.FormatToken(pytree.Leaf(token_type, token_value))
+
+
+def _MakeFormatTokenList(token_type_values):
+  return [_MakeFormatTokenLeaf(token_type, token_value)
+          for token_type, token_value in token_type_values]
+
+
+class UnwrappedLineBasicTest(unittest.TestCase):
+
+  def testConstruction(self):
+    toks = _MakeFormatTokenList([(token.DOT, '.'), (token.VBAR, '|')])
+    uwl = unwrapped_line.UnwrappedLine(20, toks)
+    self.assertEqual(20, uwl.depth)
+    self.assertEqual(['DOT', 'VBAR'], [tok.name for tok in uwl.tokens])
+
+  def testFirstLast(self):
+    toks = _MakeFormatTokenList([(token.DOT, '.'),
+                                 (token.LPAR, '('),
+                                 (token.VBAR, '|')])
+    uwl = unwrapped_line.UnwrappedLine(20, toks)
+    self.assertEqual(20, uwl.depth)
+    self.assertEqual('DOT', uwl.first.name)
+    self.assertEqual('VBAR', uwl.last.name)
+
+  def testAsCode(self):
+    toks = _MakeFormatTokenList([(token.DOT, '.'),
+                                 (token.LPAR, '('),
+                                 (token.VBAR, '|')])
+    uwl = unwrapped_line.UnwrappedLine(2, toks)
+    self.assertEqual('    . ( |', uwl.AsCode())
+
+  def testAppendToken(self):
+    uwl = unwrapped_line.UnwrappedLine(0)
+    uwl.AppendToken(_MakeFormatTokenLeaf(token.LPAR, '('))
+    uwl.AppendToken(_MakeFormatTokenLeaf(token.RPAR, ')'))
+    self.assertEqual(['LPAR', 'RPAR'], [tok.name for tok in uwl.tokens])
+
+  def testAppendNode(self):
+    uwl = unwrapped_line.UnwrappedLine(0)
+    uwl.AppendNode(pytree.Leaf(token.LPAR, '('))
+    uwl.AppendNode(pytree.Leaf(token.RPAR, ')'))
+    self.assertEqual(['LPAR', 'RPAR'], [tok.name for tok in uwl.tokens])
+
+
+class UnwrappedLineFormattingInformationTest(unittest.TestCase):
+
+  def _ParseAndUnwrap(self, code):
+    tree = pytree_utils.ParseCodeToTree(code)
+    comment_splicer.SpliceComments(tree)
+    subtype_assigner.AssignSubtypes(tree)
+    split_penalty.ComputeSplitPenalties(tree)
+
+    uwlines = pytree_unwrapper.UnwrapPyTree(tree)
+    for i, uwline in enumerate(uwlines):
+      uwlines[i] = unwrapped_line.UnwrappedLine(
+          uwline.depth, [ft for ft in uwline.tokens
+                         if ft.name not in pytree_utils.NONSEMANTIC_TOKENS])
+    return uwlines
+
+  def testFuncDef(self):
+    code = textwrap.dedent(r'''
+      def f(a, b):
+        pass
+      ''')
+    uwlines = self._ParseAndUnwrap(code)
+    uwlines[0].CalculateFormattingInformation()
+
+    f = uwlines[0].tokens[1]
+    self.assertFalse(f.can_break_before)
+    self.assertFalse(f.must_break_before)
+    self.assertEqual(f.split_penalty, split_penalty.UNBREAKABLE)
+
+    lparen = uwlines[0].tokens[2]
+    self.assertFalse(lparen.can_break_before)
+    self.assertFalse(lparen.must_break_before)
+    self.assertEqual(lparen.split_penalty, split_penalty.UNBREAKABLE)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(UnwrappedLineBasicTest))
+  result.addTests(unittest.makeSuite(UnwrappedLineFormattingInformationTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/yapftests/yapf_test.py b/yapftests/yapf_test.py
new file mode 100644
index 0000000..8c2650c
--- /dev/null
+++ b/yapftests/yapf_test.py
@@ -0,0 +1,309 @@
+# -*- coding: utf-8 -*-
+# Copyright 2015 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for yapf.yapf."""
+
+import io
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import textwrap
+import unittest
+
+from yapf.yapflib import yapf_api
+
+ROOT_DIR = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
+YAPF_BINARY = [sys.executable, '-m', 'yapf']
+
+
+class YapfTest(unittest.TestCase):
+
+  def _Check(self, unformatted_code, expected_formatted_code):
+    formatted_code = yapf_api.FormatCode(unformatted_code)
+    self.assertEqual(expected_formatted_code, formatted_code)
+
+  def testSimple(self):
+    unformatted_code = textwrap.dedent(u"""\
+        print('foo')
+        """)
+    self._Check(unformatted_code, unformatted_code)
+
+
+class CommandLineTest(unittest.TestCase):
+  """Test how calling yapf from the command line acts."""
+
+  def setUp(self):
+    self.test_tmpdir = tempfile.mkdtemp()
+
+  def tearDown(self):
+    shutil.rmtree(self.test_tmpdir)
+
+  def testUnicodeEncodingPipedToFile(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def foo():
+          print('⇒')
+        """)
+
+    with tempfile.NamedTemporaryFile(suffix='.py',
+                                     dir=self.test_tmpdir) as outfile:
+      with tempfile.NamedTemporaryFile(suffix='.py',
+                                       dir=self.test_tmpdir) as testfile:
+        testfile.write(unformatted_code.encode('UTF-8'))
+        subprocess.check_call(YAPF_BINARY + ['--diff', testfile.name],
+                              stdout=outfile)
+
+  def testInPlaceReformatting(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def foo():
+          x = 37
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def foo():
+          x = 37
+        """)
+
+    with tempfile.NamedTemporaryFile(suffix='.py',
+                                     dir=self.test_tmpdir) as testfile:
+      testfile.write(unformatted_code.encode('UTF-8'))
+      testfile.seek(0)
+
+      p = subprocess.Popen(YAPF_BINARY + ['--in-place', testfile.name])
+      p.wait()
+
+      with io.open(testfile.name, mode='r', newline='') as fd:
+        reformatted_code = fd.read()
+
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testReadFromStdin(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def foo():
+          x = 37
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def foo():
+          x = 37
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testReadSingleLineCodeFromStdin(self):
+    unformatted_code = textwrap.dedent(u"""\
+        if True: pass
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        if True: pass
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testEncodingVerification(self):
+    unformatted_code = textwrap.dedent(u"""\
+        '''The module docstring.'''
+        # -*- coding: utf-8 -*-
+        def f():
+            x = 37
+        """)
+
+    with tempfile.NamedTemporaryFile(suffix='.py',
+                                     dir=self.test_tmpdir) as outfile:
+      with tempfile.NamedTemporaryFile(suffix='.py',
+                                       dir=self.test_tmpdir) as testfile:
+        testfile.write(unformatted_code.encode('UTF-8'))
+        subprocess.check_call(YAPF_BINARY + ['--diff', testfile.name],
+                              stdout=outfile)
+
+  def testReformattingSpecificLines(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY + ['--lines', '1-2'],
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testReformattingSkippingLines(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        # yapf: disable
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        # yapf: enable
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        # yapf: disable
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+        # yapf: enable
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testReformattingSkippingToEndOfFile(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        # yapf: disable
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def f():
+          def e():
+            while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and
+                   xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) ==
+                   'bbbbbbb'):
+              pass
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        # yapf: disable
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def f():
+          def e():
+            while (xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa' and
+                   xxxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz].aaaaaaaa[0]) ==
+                   'bbbbbbb'):
+              pass
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testReformattingSkippingSingleLine(self):
+    unformatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):  # yapf: disable
+            pass
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        def h():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and
+              xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):
+            pass
+
+
+        def g():
+          if (xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0]) == 'aaaaaaaaaaa' and xxxxxxxxxxxx.yyyyyyyy(zzzzzzzzzzzzz[0].mmmmmmmm[0]) == 'bbbbbbb'):  # yapf: disable
+            pass
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+  def testDisableWholeDataStructure(self):
+    unformatted_code = textwrap.dedent(u"""\
+        A = set([
+            'hello',
+            'world',
+        ])  # pyformat: disable
+        """)
+    expected_formatted_code = textwrap.dedent(u"""\
+        A = set([
+            'hello',
+            'world',
+        ])  # pyformat: disable
+        """)
+
+    p = subprocess.Popen(YAPF_BINARY,
+                         stdout=subprocess.PIPE,
+                         stdin=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    reformatted_code, stderrdata = p.communicate(input=unformatted_code)
+    self.assertIsNone(stderrdata)
+    self.assertEqual(reformatted_code, expected_formatted_code)
+
+
+def suite():
+  result = unittest.TestSuite()
+  result.addTests(unittest.makeSuite(YapfTest))
+  result.addTests(unittest.makeSuite(CommandLineTest))
+  return result
+
+
+if __name__ == '__main__':
+  unittest.main()