Skip to content

Commit

Permalink
[feat] Create strip command
Browse files Browse the repository at this point in the history
  • Loading branch information
tohanss authored Aug 6, 2020
1 parent bcab711 commit a13f420
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 33 deletions.
32 changes: 17 additions & 15 deletions repobee_sanitizer/_sanitize.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,55 @@
from typing import List, Iterable, Optional


def sanitize_file(file_abs_path: pathlib.Path) -> Optional[str]:
def sanitize_file(
file_abs_path: pathlib.Path, strip: bool = False
) -> Optional[str]:
"""Runs the sanitization protocol on a given file. This can either remove
the file or give back a sanitized version. File must be syntax checked
before running this.
Args:
file_abs_path: The absolute file path to the file you wish to
sanitize.
sanitize.
Returns:
We return the sanitized output text, but only if the file was not
The sanitized output text, but only if the file was not
removed.
"""
text = file_abs_path.read_text()
lines = text.split("\n")
if _syntax.contained_marker(lines[0]) == Markers.SHRED:
file_abs_path.unlink()
return None
else:
sanitized_string = _sanitize(lines)
sanitized_string = _sanitize(lines, strip=False)
return "\n".join(sanitized_string)


def sanitize_text(content: str) -> str:
def sanitize_text(content: str, strip: bool = False) -> str:
"""A function to directly sanitize given content.
Args:
Content to be sanitized.
"""
lines = content.split("\n")
_syntax.check_syntax(lines)
sanitized_string = _sanitize(lines)
sanitized_string = _sanitize(lines, strip)
return "\n".join(sanitized_string)


def _sanitize(lines: List[str]) -> Iterable[str]:
def _sanitize(lines: List[str], strip: bool = False) -> Iterable[str]:
keep = True
prefix_length = 0
for line in lines:
marker = _syntax.contained_marker(line)
if marker == Markers.START:
prefix = re.match(rf"(.*?){Markers.START.value}", line).group(1)
prefix_length = len(prefix)
keep = False
elif marker in [Markers.REPLACE, Markers.END]:
if marker == Markers.END:
prefix_length = 0
prefix_length = len(prefix) if not strip else 0
keep = strip
elif marker == Markers.REPLACE:
keep = not strip
elif marker == Markers.END:
prefix_length = 0
keep = True
continue
if keep:
if keep and not marker:
yield line[prefix_length:]
7 changes: 4 additions & 3 deletions repobee_sanitizer/_sanitize_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ def sanitize_files(
for relpath in file_relpaths:
file_abspath = basedir / str(relpath)
sanitized_text = _sanitize.sanitize_file(file_abspath)
if sanitized_text:
if sanitized_text is None:
file_abspath.unlink()
LOGGER.info(f"Shredded file {relpath}")
else:
relpath.write_text_relative_to(
data=sanitized_text, basedir=basedir
)
LOGGER.info(f"Sanitized {relpath}")
else:
LOGGER.info(f"Shredded file {relpath}")

return []

Expand Down
5 changes: 4 additions & 1 deletion repobee_sanitizer/sanitizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class SanitizeFile(plug.Plugin, plug.cli.Command):

infile = plug.cli.positional(converter=pathlib.Path)
outfile = plug.cli.positional(converter=pathlib.Path)
strip = plug.cli.flag(
help="Instead of sanitizing, remove all sanitizer syntax from the file"
)

def command(self, api) -> Optional[plug.Result]:
"""A callback function that runs the sanitization protocol on a given
Expand All @@ -111,7 +114,7 @@ def command(self, api) -> Optional[plug.Result]:
name="sanitize-file", msg=msg, status=plug.Status.ERROR,
)

result = _sanitize.sanitize_file(self.infile)
result = _sanitize.sanitize_file(self.infile, strip=self.strip)
if result:
self.outfile.write_text(result)

Expand Down
15 changes: 13 additions & 2 deletions tests/helpers/testhelpers.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
"""Helper functions for the test suite."""

import pathlib
import collections

from typing import Iterable, Tuple

INPUT_FILENAME = "input.in"
OUTPUT_FILENAME = "output.out"
INVERSE_FILENAME = "inverse.out"

TEST_CASE_DIR = pathlib.Path(__file__).parent.parent / "test_case_files"

VALID_CASES_BASEDIR = TEST_CASE_DIR / "valid"
INVALID_CASES_BASEDIR = TEST_CASE_DIR / "invalid"

RESOURCES_BASEDIR = pathlib.Path(__file__).parent.parent / "resources"


TestData = collections.namedtuple("TestData", "inp out inverse".split())


def discover_test_cases(
test_case_base: pathlib.Path,
) -> Iterable[pathlib.Path]:
Expand All @@ -26,7 +32,11 @@ def _is_test_dir(d):
return

children = [f.name for f in d.iterdir()]
return INPUT_FILENAME in children and OUTPUT_FILENAME in children
return (
INPUT_FILENAME in children
and OUTPUT_FILENAME in children
and INVERSE_FILENAME in children
)

return filter(_is_test_dir, test_case_base.rglob("*"))

Expand Down Expand Up @@ -54,7 +64,8 @@ def generate_invalid_test_cases():
def read_valid_test_case_files(test_case_dir: pathlib.Path) -> Tuple[str, str]:
inp = (test_case_dir / INPUT_FILENAME).read_text(encoding="utf8")
out = (test_case_dir / OUTPUT_FILENAME).read_text(encoding="utf8")
return inp, out
inverse = (test_case_dir / INVERSE_FILENAME).read_text(encoding="utf8")
return TestData(inp, out, inverse)


def get_test_image_path() -> pathlib.Path:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class StackTest {
@Test
public void topIsLastPushedValue() {
// Arrange
int value = 1338;

// Act
emptyStack.push(value);
stack.push(value);

int emptyStackTop = emptyStack.top();
int stackTop = stack.top();

// Assert
assertThat(emptyStackTop, equalTo(value));
assertThat(stackTop, equalTo(value));
}
}
18 changes: 18 additions & 0 deletions tests/test_case_files/valid/remove/raw/junit_test_case/inverse.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class StackTest {
@Test
public void topIsLastPushedValue() {
// Arrange
int value = 1338;

// Act
emptyStack.push(value);
stack.push(value);

int emptyStackTop = emptyStack.top();
int stackTop = stack.top();

// Assert
assertThat(emptyStackTop, equalTo(value));
assertThat(stackTop, equalTo(value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class StackTest {
@Test
public void topIsLastPushedValue() {
// Arrange
int value = 1338;

// Act
emptyStack.push(value);
stack.push(value);

int emptyStackTop = emptyStack.top();
int stackTop = stack.top();

// Assert
assertThat(emptyStackTop, equalTo(value));
assertThat(stackTop, equalTo(value));
}
}
18 changes: 18 additions & 0 deletions tests/test_case_files/valid/replace/raw/junit_test_cas/inverse.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class StackTest {
@Test
public void topIsLastPushedValue() {
// Arrange
int value = 1338;

// Act
emptyStack.push(value);
stack.push(value);

int emptyStackTop = emptyStack.top();
int stackTop = stack.top();

// Assert
assertThat(emptyStackTop, equalTo(value));
assertThat(stackTop, equalTo(value));
}
}
30 changes: 23 additions & 7 deletions tests/test_ext_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ def test_sanitize_valid_file(self, sanitizer_config, tmpdir):
/ "prefixed"
/ "junit_test_case"
)
inp_text, out_text = testhelpers.read_valid_test_case_files(
test_case_dir
)
data = testhelpers.read_valid_test_case_files(test_case_dir)
inp_text = data.inp
out_text = data.out

infile = pathlib.Path(tmpdir) / "input.in"
infile.write_text(inp_text)
Expand All @@ -41,15 +41,18 @@ def test_sanitize_valid_file(self, sanitizer_config, tmpdir):

assert outfile.read_text(encoding="utf8") == out_text

def test_removes_file_with_shred_marker(self, sanitizer_config, fake_repo):
def test_does_not_creat_file_with_shred_marker(
self, sanitizer_config, fake_repo
):
"""Test that sanitize-file removes a file containing a shred marker."""
file_name = "valid-shred-marker.in"
file_src_path = fake_repo.path / file_name
file_dst_path = fake_repo.path / "inverse.out"
shutil.copy(testhelpers.get_resource(file_name), file_src_path)

run_repobee(f"sanitize file {file_src_path} {file_src_path}".split())
run_repobee(f"sanitize file {file_src_path} {file_dst_path}".split())

assert not file_src_path.is_file()
assert not file_dst_path.is_file()

def test_invalid_file_return_error_status(self, fake_repo):
"""Test that sanitize-file returns a PlugResult with status ERROR when
Expand All @@ -72,6 +75,18 @@ def test_invalid_file_return_error_status(self, fake_repo):
in result.msg
)

def test_strip_flag(self, fake_repo):
"""Tests that stripping a file works properly"""
file_name = "valid-shred-marker.in"
file_src_path = fake_repo.path / file_name
shutil.copy(testhelpers.get_resource(file_name), file_src_path)

run_repobee(
f"sanitize file {file_src_path} {file_src_path} --strip".split()
)

assert file_src_path.is_file()


class TestSanitizeRepo:
def test_no_commit(self, sanitizer_config, fake_repo):
Expand Down Expand Up @@ -449,7 +464,8 @@ def fake_repo(tmpdir) -> _FakeRepoInfo:
fake_repo_path = pathlib.Path(tmpdir)
file_infos = []
for raw_case, id_ in zip(*testhelpers.generate_valid_test_cases()):
input_text, expected_output_text = raw_case
input_text = raw_case.inp
expected_output_text = raw_case.out
output_path = fake_repo_path / id_
output_path.parent.mkdir(parents=True)
output_path.write_text(input_text)
Expand Down
9 changes: 4 additions & 5 deletions tests/test_sanitze.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ def test_sanitize_invalid(text: str):
assert _syntax.check_syntax(text)


@pytest.mark.parametrize(
"inp,expected", VALID_TEST_CASE_ARGS, ids=VALID_TEST_CASE_IDS
)
def test_sanitize_valid(inp: str, expected: str):
@pytest.mark.parametrize("data", VALID_TEST_CASE_ARGS, ids=VALID_TEST_CASE_IDS)
def test_sanitize_valid(data: testhelpers.TestData):
"""Test sanitizing valid cases with predefined expected outputs. Input
for this test function is generated by the pytest_generate_tests
hook.
"""
assert _sanitize.sanitize_text(inp) == expected
assert _sanitize.sanitize_text(data.inp) == data.out
assert _sanitize.sanitize_text(data.inp, strip=True) == data.inverse

0 comments on commit a13f420

Please sign in to comment.