Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart committed Nov 7, 2022
1 parent 39a2771 commit d1dcba1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 85 deletions.
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,12 @@ impl RustNotify {
CHANGE_MODIFIED
}
}
EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => CHANGE_MOVED,
EventKind::Modify(ModifyKind::Name(RenameMode::From)) => CHANGE_DELETED,
EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => {
let mut changes = changes_clone.lock().unwrap();
changes.remove(&(CHANGE_DELETED, path.clone(), EMPTY_STRING));
CHANGE_MOVED
}
EventKind::Remove(_) => CHANGE_DELETED,
_ => return,
};
Expand Down
2 changes: 1 addition & 1 deletion tests/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def generate_code_chunks(*directories: str):
@pytest.mark.filterwarnings('ignore:The loop argument is deprecated:DeprecationWarning')
@pytest.mark.parametrize('module_name,source_code', generate_code_chunks('watchfiles', 'docs'))
def test_docs_examples(module_name, source_code, import_execute, mocker, mock_rust_notify: 'MockRustType'):
mock_rust_notify([{(1, 'foo.txt'), (2, 'bar.py')}])
mock_rust_notify([{(1, 'foo.txt', ''), (2, 'bar.py', '')}])
mocker.patch('watchfiles.run.spawn_context.Process')
mocker.patch('watchfiles.run.os.kill')

Expand Down
24 changes: 12 additions & 12 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@


def test_ignore_file(mock_rust_notify: 'MockRustType'):
mock = mock_rust_notify([{(1, 'spam.pyc'), (1, 'spam.swp'), (1, 'foo.txt')}])
mock = mock_rust_notify([{(1, 'spam.pyc', ''), (1, 'spam.swp', ''), (1, 'foo.txt', '')}])

assert next(watch('.')) == {(Change.added, 'foo.txt')}
assert next(watch('.')) == {(Change.added, 'foo.txt', '')}
assert mock.watch_count == 1


def test_ignore_dir(mock_rust_notify: 'MockRustType'):
mock_rust_notify([{(1, '.git'), (1, str(Path('.git') / 'spam')), (1, 'foo.txt')}])
mock_rust_notify([{(1, '.git', ''), (1, str(Path('.git') / 'spam'), ''), (1, 'foo.txt', '')}])

assert next(watch('.')) == {(Change.added, 'foo.txt')}
assert next(watch('.')) == {(Change.added, 'foo.txt', '')}


def test_python(mock_rust_notify: 'MockRustType'):
mock_rust_notify([{(2, 'spam.txt'), (2, 'spam.md'), (2, 'foo.py')}])
mock_rust_notify([{(2, 'spam.txt', ''), (2, 'spam.md', ''), (2, 'foo.py', '')}])

assert next(watch('.', watch_filter=PythonFilter())) == {(Change.modified, 'foo.py')}
assert next(watch('.', watch_filter=PythonFilter())) == {(Change.modified, 'foo.py', '')}


def test_python_extensions(mock_rust_notify: 'MockRustType'):
mock_rust_notify([{(1, 'spam.txt'), (1, 'spam.md'), (1, 'foo.py')}])
mock_rust_notify([{(1, 'spam.txt', ''), (1, 'spam.md', ''), (1, 'foo.py', '')}])

f = PythonFilter(extra_extensions=('.md',))
assert next(watch('.', watch_filter=f)) == {(Change.added, 'foo.py'), (Change.added, 'spam.md')}
assert next(watch('.', watch_filter=f)) == {(Change.added, 'foo.py', ''), (Change.added, 'spam.md', '')}


def test_web_filter(mock_rust_notify: 'MockRustType'):
Expand All @@ -47,18 +47,18 @@ class WebFilter(DefaultFilter):
def __call__(self, change: Change, path: str) -> bool:
return super().__call__(change, path) and path.endswith(self.allowed_extensions)

mock_rust_notify([{(1, 'foo.txt'), (2, 'bar.html'), (3, 'spam.xlsx'), (1, '.other.js')}])
mock_rust_notify([{(1, 'foo.txt', ''), (2, 'bar.html', ''), (3, 'spam.xlsx', ''), (1, '.other.js', '')}])

assert next(watch('.', watch_filter=WebFilter())) == {(Change.modified, 'bar.html'), (Change.added, '.other.js')}
assert next(watch('.', watch_filter=WebFilter())) == {(Change.modified, 'bar.html', ''), (Change.added, '.other.js', '')}


def test_simple_function(mock_rust_notify: 'MockRustType'):
mock_rust_notify([{(1, 'added.txt'), (2, 'mod.txt'), (3, 'del.txt')}])
mock_rust_notify([{(1, 'added.txt', ''), (2, 'mod.txt', ''), (3, 'del.txt', '')}])

def only_added(change: Change, path: str) -> bool:
return change == Change.added

assert next(watch('.', watch_filter=only_added)) == {(Change.added, 'added.txt')}
assert next(watch('.', watch_filter=only_added)) == {(Change.added, 'added.txt', '')}


@pytest.mark.parametrize(
Expand Down
30 changes: 15 additions & 15 deletions tests/test_run_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_alive_terminates(mocker, mock_rust_notify: 'MockRustType', caplog):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_popen = mocker.patch('watchfiles.run.subprocess.Popen', return_value=FakePopen())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target=os.getcwd, debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 2
Expand All @@ -57,15 +57,15 @@ def test_alive_terminates(mocker, mock_rust_notify: 'MockRustType', caplog):
def test_dead_callback(mocker, mock_rust_notify: 'MockRustType'):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess(is_alive=False))
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}, {(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}, {(1, '/path/to/foobar.py', '')}])

c = mocker.MagicMock()

assert run_process('/x/y/z', target=object(), callback=c, debounce=5, step=1) == 2
assert mock_spawn_process.call_count == 3
assert mock_kill.call_count == 0
assert c.call_count == 2
c.assert_called_with({(Change.added, '/path/to/foobar.py')})
c.assert_called_with({(Change.added, '/path/to/foobar.py', '')})


@pytest.mark.skipif(sys.platform != 'win32', reason='no need to test this except on windows')
Expand All @@ -85,7 +85,7 @@ def test_split_cmd_posix():
def test_alive_doesnt_terminate(mocker, mock_rust_notify: 'MockRustType'):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess(exitcode=None))
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target=object(), debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 2
Expand All @@ -104,7 +104,7 @@ def test_sigint_timeout(mocker, mock_rust_notify: 'MockRustType', caplog):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcessTimeout())

mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target=object(), debounce=5, step=1, sigint_timeout='sigint_timeout') == 1
assert mock_spawn_process.call_count == 2
Expand All @@ -124,18 +124,18 @@ def test_start_process(mocker):
def test_start_process_env(mocker):
mock_process = mocker.patch('watchfiles.run.spawn_context.Process')
v = object()
changes = [(Change.added, 'a.py'), (Change.modified, 'b.py'), (Change.deleted, 'c.py')] # use a list to keep order
changes = [(Change.added, 'a.py', ''), (Change.modified, 'b.py', ''), (Change.deleted, 'c.py', '')] # use a list to keep order
start_process(v, 'function', (1, 2, 3), {}, changes)
assert mock_process.call_count == 1
mock_process.assert_called_with(target=v, args=(1, 2, 3), kwargs={})
assert os.getenv('WATCHFILES_CHANGES') == '[["added", "a.py"], ["modified", "b.py"], ["deleted", "c.py"]]'
assert os.getenv('WATCHFILES_CHANGES') == '[["added", "a.py", ""], ["modified", "b.py", ""], ["deleted", "c.py", ""]]'


def test_function_string_not_win(mocker, mock_rust_notify: 'MockRustType', caplog):
caplog.set_level('DEBUG', 'watchfiles')
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target='os.getcwd', debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 2
Expand All @@ -150,7 +150,7 @@ def test_function_string_not_win(mocker, mock_rust_notify: 'MockRustType', caplo
def test_function_list(mocker, mock_rust_notify: 'MockRustType'):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target=['os.getcwd'], debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 2
Expand All @@ -160,7 +160,7 @@ def test_function_list(mocker, mock_rust_notify: 'MockRustType'):
async def test_async_alive_terminates(mocker, mock_rust_notify: 'MockRustType'):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

callback_calls = []

Expand All @@ -170,13 +170,13 @@ async def c(changes):
assert await arun_process('/x/y/async', target=object(), callback=c, debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 2
assert mock_kill.call_count == 2 # kill in loop + final kill
assert callback_calls == [{(Change.added, '/path/to/foobar.py')}]
assert callback_calls == [{(Change.added, '/path/to/foobar.py', '')}]


async def test_async_sync_callback(mocker, mock_rust_notify: 'MockRustType'):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foo.py')}, {(2, '/path/to/bar.py')}])
mock_rust_notify([{(1, '/path/to/foo.py', '')}, {(2, '/path/to/bar.py', '')}])

callback_calls = []

Expand All @@ -188,7 +188,7 @@ async def test_async_sync_callback(mocker, mock_rust_notify: 'MockRustType'):
)
assert mock_spawn_process.call_count == 3
assert mock_kill.call_count == 3
assert callback_calls == [{(Change.added, '/path/to/foo.py')}, {(Change.modified, '/path/to/bar.py')}]
assert callback_calls == [{(Change.added, '/path/to/foo.py', '')}, {(Change.modified, '/path/to/bar.py', '')}]


def test_run_function(tmp_work_path: Path, create_test_function):
Expand Down Expand Up @@ -227,7 +227,7 @@ def test_command(mocker, mock_rust_notify: 'MockRustType', caplog):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_popen = mocker.patch('watchfiles.run.subprocess.Popen', return_value=FakePopen())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target='echo foobar', debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 0
Expand All @@ -242,7 +242,7 @@ def test_command_with_args(mocker, mock_rust_notify: 'MockRustType', caplog):
mock_spawn_process = mocker.patch('watchfiles.run.spawn_context.Process', return_value=FakeProcess())
mock_popen = mocker.patch('watchfiles.run.subprocess.Popen', return_value=FakePopen())
mock_kill = mocker.patch('watchfiles.run.os.kill')
mock_rust_notify([{(1, '/path/to/foobar.py')}])
mock_rust_notify([{(1, '/path/to/foobar.py', '')}])

assert run_process('/x/y/z', target='echo foobar', args=(1, 2), target_type='command', debounce=5, step=1) == 1
assert mock_spawn_process.call_count == 0
Expand Down
52 changes: 23 additions & 29 deletions tests/test_rust_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test_add(test_dir: Path):
watcher = RustNotify([str(test_dir)], True, False, 0, True)
(test_dir / 'new_file.txt').write_text('foobar')

assert watcher.watch(200, 50, 500, None) == {(1, str(test_dir / 'new_file.txt'))}
assert watcher.watch(200, 50, 500, None) == {(1, str(test_dir / 'new_file.txt'), '')}


def test_add_non_recursive(test_dir: Path):
Expand All @@ -22,7 +22,7 @@ def test_add_non_recursive(test_dir: Path):
(test_dir / 'new_file_non_recursive.txt').write_text('foobar')
(test_dir / 'dir_a' / 'new_file_non_recursive.txt').write_text('foobar')

assert watcher.watch(200, 50, 500, None) == {(1, str(test_dir / 'new_file_non_recursive.txt'))}
assert watcher.watch(200, 50, 500, None) == {(1, str(test_dir / 'new_file_non_recursive.txt'), '')}


def test_close(test_dir: Path):
Expand All @@ -41,7 +41,7 @@ def test_modify_write(test_dir: Path):

(test_dir / 'a.txt').write_text('this is new')

assert watcher.watch(200, 50, 500, None) == {(2, str(test_dir / 'a.txt'))}
assert watcher.watch(200, 50, 500, None) == {(2, str(test_dir / 'a.txt'), '')}


def test_modify_write_non_recursive(test_dir: Path):
Expand All @@ -51,7 +51,7 @@ def test_modify_write_non_recursive(test_dir: Path):
(test_dir / 'dir_a' / 'a_non_recursive.txt').write_text('this is new')

assert watcher.watch(200, 50, 500, None) == {
(2, str(test_dir / 'a_non_recursive.txt')),
(2, str(test_dir / 'a_non_recursive.txt'), ''),
}


Expand All @@ -61,7 +61,7 @@ def test_modify_chmod(test_dir: Path):

(test_dir / 'b.txt').chmod(0o444)

assert watcher.watch(200, 50, 500, None) == {(2, str(test_dir / 'b.txt'))}
assert watcher.watch(200, 50, 500, None) == {(2, str(test_dir / 'b.txt'), '')}


def test_delete(test_dir: Path):
Expand All @@ -70,7 +70,7 @@ def test_delete(test_dir: Path):
(test_dir / 'c.txt').unlink()

assert watcher.watch(200, 50, 500, None) == {
(3, str(test_dir / 'c.txt')),
(3, str(test_dir / 'c.txt'), ''),
}


Expand All @@ -81,7 +81,7 @@ def test_delete_non_recursive(test_dir: Path):
(test_dir / 'dir_a' / 'c_non_recursive.txt').unlink()

assert watcher.watch(200, 50, 500, None) == {
(3, str(test_dir / 'c_non_recursive.txt')),
(3, str(test_dir / 'c_non_recursive.txt'), ''),
}


Expand All @@ -99,8 +99,8 @@ def test_move_in(test_dir: Path):
(src / f).rename(dst / f)

assert watcher.watch(200, 50, 500, None) == {
(1, str(dst / 'a.txt')),
(1, str(dst / 'b.txt')),
(1, str(dst / 'a.txt'), ''),
(1, str(dst / 'b.txt'), ''),
}


Expand All @@ -116,8 +116,8 @@ def test_move_out(test_dir: Path):
(src / f).rename(dst / f)

assert watcher.watch(200, 50, 500, None) == {
(3, str(src / 'c.txt')),
(3, str(src / 'd.txt')),
(3, str(src / 'c.txt'), ''),
(3, str(src / 'd.txt'), ''),
}


Expand All @@ -133,14 +133,12 @@ def test_move_internal(test_dir: Path):
(src / f).rename(dst / f)

expected_changes = {
(3, str(src / 'e.txt')),
(3, str(src / 'f.txt')),
(1, str(dst / 'e.txt')),
(1, str(dst / 'f.txt')),
(4, str(src / 'e.txt'), str(dst / 'e.txt')),
(4, str(src / 'f.txt'), str(dst / 'f.txt')),
}
if sys.platform == 'win32':
# Windows adds a "modified" event for the dst directory
expected_changes.add((2, str(dst)))
expected_changes.add((2, str(dst), ''))

assert watcher.watch(200, 50, 500, None) == expected_changes

Expand All @@ -158,8 +156,7 @@ def test_rename(test_dir: Path):
f.rename(f.with_suffix('.new'))

assert watcher.watch(200, 50, 500, None) == {
(3, str(f)),
(1, str(test_dir / 'a.new')),
(4, str(f), str(test_dir / 'a.new')),
}


Expand All @@ -176,9 +173,9 @@ def test_watch_multiple(tmp_path: Path):

changes = watcher.watch(200, 50, 500, None)
# can compare directly since on macos creating the foo and bar directories is included in changes
assert (1, str(foo / 'foo.txt')) in changes
assert (1, str(bar / 'foo.txt')) in changes
assert not any('not_included.txt' in p for c, p in changes)
assert (1, str(foo / 'foo.txt'), '') in changes
assert (1, str(bar / 'foo.txt'), '') in changes
assert not any('not_included.txt' in p for c, p, p2 in changes)


def test_wrong_type_event(test_dir: Path, time_taken):
Expand Down Expand Up @@ -235,7 +232,7 @@ def test_return_debounce_no_timeout(test_dir: Path, time_taken):
(test_dir / 'debounce.txt').write_text('foobar')

with time_taken(50, 130):
assert watcher.watch(100, 50, 20, None) == {(1, str(test_dir / 'debounce.txt'))}
assert watcher.watch(100, 50, 20, None) == {(1, str(test_dir / 'debounce.txt'), '')}


@skip_unless_linux
Expand All @@ -260,12 +257,9 @@ def test_rename_multiple_inside(tmp_path: Path):
f3.rename(d2 / '3.txt')

assert watcher_all.watch(200, 50, 500, None) == {
(3, str(f1)),
(3, str(f2)),
(3, str(f3)),
(1, str(d2 / '1.txt')),
(1, str(d2 / '2.txt')),
(1, str(d2 / '3.txt')),
(4, str(f1), str(d2 / '1.txt')),
(4, str(f2), str(d2 / '2.txt')),
(4, str(f3), str(d2 / '3.txt')),
}


Expand All @@ -275,7 +269,7 @@ def test_polling(test_dir: Path):
(test_dir / 'test_polling.txt').write_text('foobar')

changes = watcher.watch(200, 50, 500, None)
assert (1, str(test_dir / 'test_polling.txt')) in changes # sometimes has an event modify too
assert (1, str(test_dir / 'test_polling.txt'), '') in changes # sometimes has an event modify too


def test_not_polling_repr(test_dir: Path):
Expand Down
Loading

0 comments on commit d1dcba1

Please sign in to comment.