Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

121 add line ending options 1 #132

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/fixers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ using ``-f``/``--fix``. The ``--six-unicode`` and ``--future-unicode`` options
also disable fixers that are not applicable for those options.


Options affecting all fixers
----------------------------

Normally, output files are written with the usual line endings for the platform
that python-modernize is run on (LF for Unix / Mac OS X, or CRLF for Windows).

The ``--unix-line-endings`` option writes Unix line endings regardless of the
curent platform. Similarly, the ``--windows-line-endings`` option writes Windows
line endings regardless of the current platform.


Fixers requiring six
++++++++++++++++++++

Expand Down
34 changes: 34 additions & 0 deletions libmodernize/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from __future__ import absolute_import, print_function

import sys
import os
import logging
import optparse

Expand Down Expand Up @@ -63,6 +64,10 @@ def main(args=None):
"(only useful for Python 2.6+).")
parser.add_option("--no-six", action="store_true", default=False,
help="Exclude fixes that depend on the six package.")
parser.add_option("--unix-line-endings", action="store_true", default=False,
help="Write files with Unix (LF) line endings.")
parser.add_option("--windows-line-endings", action="store_true", default=False,
help="Write files with Windows (CRLF) line endings.")

fixer_pkg = 'libmodernize.fixes'
avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg))
Expand Down Expand Up @@ -94,6 +99,15 @@ def main(args=None):
if options.print_function:
flags["print_function"] = True

if options.unix_line_endings and options.windows_line_endings:
print("--unix-line-endings and --windows-line-endings options conflict.")
return 2
linesep = None
if options.unix_line_endings:
linesep = '\n'
if options.windows_line_endings:
linesep = '\r\n'

# Set up logging handler
level = logging.DEBUG if options.verbose else logging.INFO
logging.basicConfig(format='%(name)s: %(message)s', level=level)
Expand Down Expand Up @@ -125,6 +139,26 @@ def main(args=None):
else:
requested = default_fixes
fixer_names = requested.difference(unwanted_fixes)

parameters = (fixer_names, flags, explicit, options, refactor_stdin, args)
if linesep is None or linesep == os.linesep:
return do_refactoring(*parameters)
else:
if not hasattr(refactor, '_to_system_newlines'):
print("Cannot override newline mode due to a change in lib2to3.")
return 2

old_to_system_newlines = refactor._to_system_newlines
def _to_system_newlines(s):
return s.replace('\r', '').replace('\n', linesep)
refactor._to_system_newlines = _to_system_newlines
try:
return do_refactoring(*parameters)
finally:
refactor._to_system_newlines = old_to_system_newlines


def do_refactoring(fixer_names, flags, explicit, options, refactor_stdin, args):
rt = StdoutRefactoringTool(sorted(fixer_names), flags, sorted(explicit),
options.nobackups, not options.no_diffs)

Expand Down
30 changes: 30 additions & 0 deletions tests/test_newlines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from __future__ import absolute_import

import os
from utils import check_on_input, expect_error
from test_fix_basestring import BASESTRING

TESTCASE = [x.encode('ascii') for x in BASESTRING]


def test_mixed_to_native_line_endings():
check_on_input(b'#\r\n' + TESTCASE[0],
(b'#\n' + TESTCASE[1]).replace(b'\n', os.linesep.encode('ascii')),
mode="b")

def test_windows_to_unix_line_endings():
check_on_input(TESTCASE[0].replace(b'\n', b'\r\n'),
TESTCASE[1],
extra_flags=['--unix-line-endings'],
mode="b")

def test_unix_to_windows_line_endings():
check_on_input(TESTCASE[0],
TESTCASE[1].replace(b'\n', b'\r\n'),
extra_flags=['--windows-line-endings'],
mode="b")

def test_options_conflict():
expect_error(TESTCASE[0],
extra_flags=['--unix-line-endings', '--windows-line-endings'],
mode="b")
36 changes: 27 additions & 9 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from __future__ import absolute_import

import sys
import os.path
import tempfile
import shutil

from libmodernize.main import main as modernize_main


def check_on_input(input_content, expected_content, extra_flags = []):
def check_on_input(input_content, expected_content, extra_flags=[], mode="t"):
"""
Check that input_content is fixed to expected_content, idempotently.

Expand All @@ -19,24 +20,41 @@ def check_on_input(input_content, expected_content, extra_flags = []):
tmpdirname = tempfile.mkdtemp()
try:
test_input_name = os.path.join(tmpdirname, "input.py")
with open(test_input_name, "wt") as input_file:
with open(test_input_name, "w" + mode) as input_file:
input_file.write(input_content)

def _check(this_input_content, which_check):
modernize_main(extra_flags + ["-w", test_input_name])
ret = modernize_main(extra_flags + ["-w", test_input_name])
if ret != 0:
raise AssertionError("didn't expect to fail (returned %r)" % (ret,))

output_content = ""
with open(test_input_name, "rt") as output_file:
for line in output_file:
if line:
output_content += line
with open(test_input_name, "r" + mode) as output_file:
if mode == "b":
output_content = output_file.read()
else:
output_content = "".join([line for line in output_file if line])

if output_content != expected_content:
raise AssertionError("%s\nInput:\n%sOutput:\n%s\nExpecting:\n%s" %
fmt = "%r" if mode == "b" else "%s"
raise AssertionError(("%s\nInput:\n"+fmt+"\nOutput:\n"+fmt+"\nExpecting:\n"+fmt) %
(which_check, this_input_content, output_content, expected_content))

_check(input_content, "output check failed")
if input_content != expected_content:
_check(expected_content, "idempotence check failed")
finally:
shutil.rmtree(tmpdirname)


def expect_error(input_content, extra_flags=[], mode="t"):
tmpdirname = tempfile.mkdtemp()
try:
test_input_name = os.path.join(tmpdirname, "input.py")
with open(test_input_name, "w" + mode) as input_file:
input_file.write(input_content)

ret = modernize_main(extra_flags + ["-w", test_input_name])
if ret == 0:
raise AssertionError("didn't expect to succeed")
finally:
shutil.rmtree(tmpdirname)