Skip to content

Commit

Permalink
Add option to preserve or unify line separators
Browse files Browse the repository at this point in the history
  • Loading branch information
ducminh-phan committed Jul 7, 2019
1 parent cb3ad6a commit 4af76bb
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 6 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ These instructions will get you a copy of the project up and running on your loc
keywords are left-aligned, and there is a
single space between the step keyword and the
statement.
-n, --newline [LF|CRLF] Specify the line separators when formatting
files inplace. If not specified, line
separators are preserved.
--fast / --safe If --fast given, skip the sanity checks of
file contents. [default: --safe]
--config FILE Read configuration from FILE.
--version Show the version and exit.
--help Show this message and exit.

### Config file

The tool is able to read project-specific default values for its command line options from a `.reformat-gherkin.yaml` file.
Expand Down
18 changes: 16 additions & 2 deletions reformat_gherkin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .config import read_config_file
from .core import reformat
from .errors import EmptySources
from .options import AlignmentMode, Options, WriteBackMode
from .options import AlignmentMode, NewlineMode, Options, WriteBackMode
from .report import Report
from .utils import out
from .version import __version__
Expand Down Expand Up @@ -41,6 +41,15 @@
"space between the step keyword and the statement."
),
)
@click.option(
"-n",
"--newline",
type=click.Choice([NewlineMode.LF.value, NewlineMode.CRLF.value]),
help=(
"Specify the line separators when formatting files inplace. "
"If not specified, line separators are preserved."
),
)
@click.option(
"--fast/--safe",
is_flag=True,
Expand All @@ -62,6 +71,7 @@ def main(
src: Tuple[str],
check: bool,
alignment: Optional[str],
newline: Optional[str],
fast: bool,
config: Optional[str],
) -> None:
Expand All @@ -73,9 +83,13 @@ def main(

write_back_mode = WriteBackMode.from_configuration(check)
alignment_mode = AlignmentMode.from_configuration(alignment)
newline_mode = NewlineMode.from_configuration(newline)

options = Options(
write_back=write_back_mode, step_keyword_alignment=alignment_mode, fast=fast
write_back=write_back_mode,
step_keyword_alignment=alignment_mode,
newline=newline_mode,
fast=fast,
)

report = Report(check=check)
Expand Down
6 changes: 5 additions & 1 deletion reformat_gherkin/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
StableError,
)
from .formatter import LineGenerator
from .options import Options, WriteBackMode
from .options import NewlineMode, Options, WriteBackMode
from .parser import parse
from .report import Report
from .utils import decode_bytes, diff, dump_to_file, err

REPORT_URL = "https://github.com/ducminh-phan/reformat-gherkin/issues"

NEWLINE_FROM_OPTION = {NewlineMode.CRLF: "\r\n", NewlineMode.LF: "\n"}


def find_sources(src: Tuple[str]) -> Set[Path]:
sources: Set[Path] = set()
Expand Down Expand Up @@ -55,6 +57,8 @@ def reformat_single_file(path: Path, *, options: Options) -> bool:
with open(path, "rb") as buf:
src_contents, encoding, newline = decode_bytes(buf.read())

newline = NEWLINE_FROM_OPTION.get(options.newline, newline)

try:
dst_contents = format_file_contents(src_contents, options=options)
except NothingChanged:
Expand Down
14 changes: 13 additions & 1 deletion reformat_gherkin/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,20 @@ def from_configuration(cls, alignment: Optional[str]) -> "AlignmentMode":
return AlignmentMode(alignment)


@dataclass(frozen=True, kw_only=True)
@unique
class NewlineMode(Enum):
KEEP = None
LF = "LF"
CRLF = "CRLF"

@classmethod
def from_configuration(cls, newline: Optional[str]) -> "NewlineMode":
return NewlineMode(newline)


@dataclass(frozen=True)
class Options:
write_back: WriteBackMode
step_keyword_alignment: AlignmentMode
newline: NewlineMode
fast: bool
21 changes: 21 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,27 @@ def fin():
return construct_sources


@pytest.fixture
def source_with_newline(request):
def construct_source_with_newline(newline):
tmp_file = Path(f"tmp{os.urandom(4).hex()}.feature")

with open(TEST_DIR / "data" / "valid" / "full.feature", "r") as f:
content = f.read()

with open(tmp_file, "w", newline=newline) as f:
f.write(content)

def fin():
os.remove(tmp_file)

request.addfinalizer(fin)

return tmp_file

return construct_source_with_newline


@pytest.fixture
def runner():
return CliRunner()
3 changes: 2 additions & 1 deletion tests/helpers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from reformat_gherkin.options import AlignmentMode, Options, WriteBackMode
from reformat_gherkin.options import AlignmentMode, NewlineMode, Options, WriteBackMode

OPTIONS = [
Options(
write_back=WriteBackMode.CHECK,
step_keyword_alignment=alignment_mode,
newline=NewlineMode.KEEP,
fast=False,
)
for alignment_mode in AlignmentMode
Expand Down
34 changes: 34 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from unittest.mock import patch

import attr
import pytest

from reformat_gherkin import core
Expand Down Expand Up @@ -77,3 +78,36 @@ def test_format_file_contents_no_change(options):

with pytest.raises(NothingChanged):
core.format_file_contents(formatted_content, options=options)


@pytest.mark.parametrize("newline_mode", core.NEWLINE_FROM_OPTION.keys())
@pytest.mark.parametrize("newline", core.NEWLINE_FROM_OPTION.values())
def test_line_separators_changed(source_with_newline, newline_mode, newline):
options = OPTIONS[0]
options = attr.evolve(
options, write_back=core.WriteBackMode.INPLACE, newline=newline_mode
)

source = source_with_newline(newline)

core.reformat_single_file(source, options=options)

with open(source, "rb") as buf:
_newline = core.decode_bytes(buf.read())[2]

assert _newline == core.NEWLINE_FROM_OPTION[newline_mode]


@pytest.mark.parametrize("newline", core.NEWLINE_FROM_OPTION.values())
def test_line_separators_preserved(source_with_newline, newline):
options = OPTIONS[0]
options = attr.evolve(options, write_back=core.WriteBackMode.INPLACE)

source = source_with_newline(newline)

core.reformat_single_file(source, options=options)

with open(source, "rb") as buf:
_newline = core.decode_bytes(buf.read())[2]

assert _newline == newline

0 comments on commit 4af76bb

Please sign in to comment.