Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
755e402
Fix default value syntax for docopt entry for 'spool' parameter.
suggiro Dec 31, 2017
dc82b40
Add initial tests for command line arguments.
suggiro Dec 31, 2017
8e63df5
git ignore coverage directory
suggiro Dec 31, 2017
314dc78
simple comment on pytest config argument
suggiro Dec 31, 2017
a3286f9
Added 'spool' parameter validation and coverage tests, considering de…
suggiro Dec 31, 2017
8b64901
Added 'spool' parameter validation and coverage tests, considering de…
suggiro Dec 31, 2017
6eab020
Fix README --spool default docopt description
suggiro Dec 31, 2017
f07934a
git ignore profiling files (*.prof)
suggiro Dec 31, 2017
6c1400b
More detailed error message for --spool parameter
suggiro Dec 31, 2017
efebe20
Refactor basic tests with default arguments. Added a new test for tes…
suggiro Jan 2, 2018
a87a382
Small PEP8 adjust
suggiro Jan 2, 2018
785a645
Initial --ext, <pytest_args> and <directories> command line parsing t…
suggiro Jan 2, 2018
66c8c95
Simplification of @patch declaration from method-level to class-level
suggiro Jan 2, 2018
6d9c39d
Added tests for --ignore command line parameter.
suggiro Jan 3, 2018
a243dd6
Added tests for --pdb and --wait command line parameters
suggiro Jan 3, 2018
548e06a
Added initial tests for --config command line parameter. pytest_watch…
suggiro Jan 3, 2018
1ad3d8a
README how to usage updated with fix on --ext [default: .py] definition
suggiro Jan 3, 2018
117fe1d
mock patch declaration moved to class-level.
suggiro Jan 3, 2018
1b6a0ea
Add tests for --ext ALL_EXTENSIONS and default --ext value support. T…
suggiro Jan 3, 2018
897cf5d
file moving from test_main.py -> test_command.py, according to descri…
suggiro Jan 3, 2018
b0f4b18
Added initial tests for __main__.py
suggiro Jan 3, 2018
d5e7710
Removed unused DEFAULT_EXTENSIONS constant.
suggiro Jan 4, 2018
c673b9a
Replace explicit sys.argv[1:] declaration from main() call. As sugges…
suggiro Jan 4, 2018
0f8c89b
PEP8 line length limits applied to stderr messages
suggiro Jan 4, 2018
d7828e9
PEP8 line length applied to test_command.py
suggiro Jan 4, 2018
6bd4c34
Added requirements-test.txt file and declared it into setup.py
suggiro Jan 4, 2018
26159fd
'mock' lib is necessary for setup.py test under python2 environment. …
suggiro Jan 4, 2018
8a0d80d
Replace verbose unittest for simple assertions to assert.
suggiro Jan 4, 2018
309a8cf
classless tests over simple functions
suggiro Jan 4, 2018
ef774dc
Add Travis-CI descriptor
suggiro Jan 4, 2018
343ebc4
Fix Travis requirements-test.txt declaration
suggiro Jan 4, 2018
636d2d9
Fix travis.yml definition and add python 2.7.14 version to be tested
suggiro Jan 4, 2018
4f9fc32
Added OS list to Travis-CI descriptor: Linux, OSX, Windows
suggiro Jan 4, 2018
bb82b1d
Travis-CI doesn't support Windows VM. It was removed from definitions
suggiro Jan 4, 2018
dd3cfbf
Travis-CI doesn't support python on OSX. This os was removed from tra…
suggiro Jan 4, 2018
8c78d16
_split_recursive changed to keep and return the same ignore directory…
suggiro Jan 4, 2018
a02236f
Move run_cli for its own line.
suggiro Jan 5, 2018
839acc7
Asserting with the assert statement (without unittest assert* methods)
suggiro Jan 5, 2018
2fa4235
Initial tests and small fix over pytest_watch.watcher._split_recursive
suggiro Jan 6, 2018
b1c3197
remove os.path.basename from ignore testes
suggiro Jan 6, 2018
61414b3
Move join declaration outside for loop
suggiro Jan 7, 2018
dcfbe36
Added tests for hooks. Initially, beforerun and afterrun with Keyboar…
suggiro Jan 7, 2018
b9ac9f4
Added initial tests wid subprocess.Popen without block a forked proce…
suggiro Jan 10, 2018
da4ee19
Initial tests for pytest_watch.watcher.EventListener
suggiro Jan 10, 2018
ac44193
Add basic tests for watched events.
suggiro Jan 10, 2018
24a78a9
Improvements over test_event_move_file, covering os.path.relpath call…
suggiro Jan 10, 2018
e514278
standard name for test_watcher_* tests files
suggiro Jan 10, 2018
135b7de
Tests over EventListener for observer, not observed extensions.
suggiro Jan 11, 2018
973b3b5
fix cumulative test folder create&destroy
suggiro Jan 11, 2018
dc6a326
SImple comment. Next step will be group variables closest to its usage
suggiro Jan 11, 2018
2557cc2
Added tests for not existent directories.
suggiro Jan 11, 2018
b915f81
fix test_afterrun* methods conflicts
suggiro Jan 11, 2018
158ca45
Fix tests over afterrun and beforerun, removing redundant Popen calls…
suggiro Jan 13, 2018
7e272aa
refactor redundant test cases and method-level patch
suggiro Jan 14, 2018
bcfd391
FileNotFoundError doesn't works for python2 (<py3.5). It was replaced…
suggiro Jan 15, 2018
e8572d8
General synatx & typo fixes
suggiro Jan 20, 2018
9a7ace0
pep8 style over test_ code
suggiro Jan 21, 2018
13029b7
Added https://raw.githubusercontent.com/github/gitignore/master/Pytho…
suggiro Jan 22, 2018
515d898
Change .gitignore reference
suggiro Jan 22, 2018
da3e334
pep8 imports
suggiro Feb 11, 2018
a0fbe45
Added supported python versions to travis
suggiro Feb 11, 2018
06b6da6
Change mock assertion calls: assert_called_once for compatibility wit…
suggiro Feb 11, 2018
5c4ff37
travis test over 3.5 and 3.7-dev
suggiro Feb 11, 2018
7adcb13
travis remove tests over 3.7-dev
suggiro Feb 11, 2018
0be301a
Reverting .gitignore to lean version containing only project inherent…
suggiro Feb 22, 2018
6f1638c
Initial clean up for unittest.TestCase and other dependencies of fram…
suggiro Feb 22, 2018
81f5c63
requirements.txt and requirements-test.txt dependencies were inserted…
suggiro Feb 23, 2018
3849636
Move default pytest_watcher.watch mock to pytest-mock mocker usage pa…
suggiro Feb 23, 2018
2e250cb
Added pytest-mock dependency to setup.py & requirements-test.txt
suggiro Feb 23, 2018
8d699d5
Added DEPS_TESTING to DEPS_QA
suggiro Feb 23, 2018
77e529b
Added codecov.com support to Travis-CI
suggiro Feb 23, 2018
47adfc3
Add -v verbosity to travis-ci test coverage
suggiro Feb 23, 2018
bbe37af
split summary output definitions from core watcher module.
suggiro Feb 23, 2018
1f597c8
For tests/mock purposes, ctype was moved to module level import section.
suggiro Feb 25, 2018
e39858e
Added tests for helpers.send_keyboard_event, covering is_windows (Tru…
suggiro Feb 25, 2018
3c8ff1b
Compatibility with 3- versions. Format string was introduced. Now, ro…
suggiro Feb 25, 2018
1f8888f
Fix test_helpers for python 2.7 compatibility and some simplifications
suggiro Feb 25, 2018
d5eefb9
Fix test_helpers for python 2.7 compatibility and some simplifications
suggiro Feb 25, 2018
3932987
pep8 updates
suggiro Feb 25, 2018
f62cd37
Remove conflicting pdbpp and pytest-pdb. It should be analysed why th…
suggiro Feb 25, 2018
1f11440
Added helpers.clear and helpers.beep tests & fixtures
suggiro Feb 26, 2018
828c6eb
Added pytest_watch.util test, covering Exception handling
suggiro Feb 26, 2018
299067f
Added pytest_watch.util test, covering Exception handling
suggiro Feb 26, 2018
e6b26b8
Add tests for pytest_watch.helpers samepath & deque_all
suggiro Feb 26, 2018
5f2cf64
Added test for named space files on samepath
suggiro Feb 26, 2018
03c243b
gitignore coverage.xml
suggiro Mar 9, 2018
2ef5b86
Added pytest-runner to setup.py and 'setup.py test' alias for 'pytest'
suggiro Mar 9, 2018
42a64da
Skip tests on win32 system for checking real path for symlinks. Win32…
Mar 12, 2018
c944899
wrapper for build win32 command line path
Mar 12, 2018
e0beb47
subprocess.call working for Windows paths
Mar 18, 2018
61083c9
Create appveyor.yml
apast Apr 12, 2018
1913c66
Update appveyor.yml
apast Apr 12, 2018
bb39e90
Added classifier Famework :: Pytest for better pypi index classification
suggiro Apr 12, 2018
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
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
source=pytest_watch
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ env
.cache
*.so
*.py[cod]
.eggs
.coverage
.coverage.*
.pytest_cache
.python-version

# OS-specific files
.DS_Store
Desktop.ini
Thumbs.db
coverage.xml
22 changes: 22 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
language: python
python:
- 2.7
- pypy2.7-5.8.0
- 3.4
- 3.5.4
- 3.6
- pypy3.5-5.8.0

os:
- linux

cache: pip

install:
- pip install -e ".[qa]"

script:
- python -m pytest --cov=pytest_watch --cov-report=term-missing -v pytest_watch

after_success:
- codecov --token=$CODECOV_TOKEN
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Options:
--ignore <dir> Ignore directory from being watched and during
collection (multi-allowed).
--ext <exts> Comma-separated list of file extensions that can
trigger a new test run when changed (default: .py).
trigger a new test run when changed [default: .py].
Use --ext=* to allow any file (including .pyc).
--config <file> Load configuration from `file` instead of trying to
locate one of the implicit configuration files.
Expand All @@ -129,7 +129,7 @@ Options:
--pdb Start the interactive Python debugger on errors.
This also enables --wait to prevent pdb interruption.
--spool <delay> Re-run after a delay (in milliseconds), allowing for
more file system events to queue up (default: 200 ms).
more file system events to queue up [default: 200].
-p --poll Use polling instead of OS events (useful in VMs).
-v --verbose Increase verbosity of the output.
-q --quiet Decrease verbosity of the output (precedence over -v).
Expand Down
4 changes: 4 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: 1.0.{build}

build_script:
- cmd: python setup.py test
10 changes: 7 additions & 3 deletions pytest_watch/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
:license: MIT, see LICENSE for more details.
"""

import os
import sys

def run_cli():
import os
import sys

if __name__ == '__main__':
sys.path.append(os.path.dirname(__file__))

from pytest_watch.command import main
main()


if __name__ == '__main__':
run_cli()
32 changes: 21 additions & 11 deletions pytest_watch/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
--ignore <dir> Ignore directory from being watched and during
collection (multi-allowed).
--ext <exts> Comma-separated list of file extensions that can
trigger a new test run when changed (default: .py).
trigger a new test run when changed [default: .py].
Copy link
Owner

@joeyespo joeyespo Jan 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are brackets a common for default values in CLI tool --help texts? Nevermind. Just noticed docopt uses brackets in their docs. Thanks for updating 👍

Use --ext=* to allow any file (including .pyc).
--config <file> Load configuration from `file` instead of trying to
locate one of the implicit configuration files.
Expand All @@ -29,7 +29,7 @@
--pdb Start the interactive Python debugger on errors.
This also enables --wait to prevent pdb interruption.
--spool <delay> Re-run after a delay (in milliseconds), allowing for
more file system events to queue up (default: 200 ms).
more file system events to queue up [default: 200].
-p --poll Use polling instead of OS events (useful in VMs).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, nice removal of the redundant ms.

-v --verbose Increase verbosity of the output.
-q --quiet Decrease verbosity of the output (precedence over -v).
Expand All @@ -55,6 +55,8 @@
def main(argv=None):
"""
The entry point of the application.

argv -- List of strings to parse. The default is taken from sys.argv[1:].
"""
if argv is None:
argv = sys.argv[1:]
Expand All @@ -68,6 +70,8 @@ def main(argv=None):
# Get paths and initial pytest arguments
directories = args['<directory>']
pytest_args = list(directories)

# Merge pytest arguments and directories
if '--' in directories:
index = directories.index('--')
directories = directories[:index]
Expand All @@ -76,6 +80,8 @@ def main(argv=None):
# Adjust pytest and --collect-only args
for ignore in args['--ignore']:
pytest_args.extend(['--ignore', ignore])

# Set pytest config file
if args['--config']:
pytest_args.extend(['-c', args['--config']])

Expand All @@ -87,23 +93,27 @@ def main(argv=None):
if args['--pdb']:
pytest_args.append('--pdb')

# Parse extensions
# Parse extensions [default: .py]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition of comments 👍 Even more so with the defaults right there.

if args['--ext'] == '*':
extensions = ALL_EXTENSIONS
elif args['--ext']:
extensions = [('.' if not e.startswith('.') else '') + e
for e in args['--ext'].split(',')]
else:
extensions = None
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I see fixing the default value in docopt allows you to remove this. Very nice 👍


# Parse numeric arguments
spool = args['--spool']
if spool is not None:
try:
spool = int(spool)
except ValueError:
sys.stderr.write('Error: Spool must be an integer.\n')
return 2
try:
spool = int(spool)
except ValueError:
sys.stderr.write('Error: Spool (--spool {}) must be an integer.\n'
.format(spool))
return 2

if spool < 0:
sys.stderr.write('Error: Spool value(--spool {}) must be positive'
' integer\n'
.format(spool))
return 2

# Run pytest and watch for changes
return watch(directories=directories,
Expand Down
4 changes: 2 additions & 2 deletions pytest_watch/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def _collect_config(pytest_args, silent=True):
except (Exception, SystemExit):
pass
# Print message and run again without silencing
print('Error: Could not run --collect-only to handle the pytest config '
'file. Trying again without silencing output...',
print('Error: Could not run --collect-only to handle the pytest '
'config file. Trying again without silencing output...',
file=sys.stderr)

return _run_pytest_collect(pytest_args)
Expand Down
11 changes: 7 additions & 4 deletions pytest_watch/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ctypes
import os
import signal
import subprocess
Expand Down Expand Up @@ -51,12 +52,15 @@ def dequeue_all(queue, spool=None):
return items


def canonize_path(path):
return os.path.realpath(path)


def samepath(left, right):
"""
Determines whether two paths are the same.
Determines whether two paths are the same based on their absolute paths.
"""
return (os.path.abspath(os.path.normcase(left)) ==
os.path.abspath(os.path.normcase(right)))
return canonize_path(left) == canonize_path(right)


def send_keyboard_interrupt(proc):
Expand All @@ -70,7 +74,6 @@ def send_keyboard_interrupt(proc):
os.kill(0, signal.CTRL_C_EVENT)
except AttributeError:
# Python 2.6 and below
import ctypes
ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, 0)
# Immediately throws KeyboardInterrupt from the simulated CTRL-C
proc.wait()
Expand Down
81 changes: 81 additions & 0 deletions pytest_watch/summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import time

from colorama import Fore, Style


STYLE_BRIGHT = Fore.WHITE + Style.NORMAL + Style.BRIGHT
STYLE_HIGHLIGHT = Fore.CYAN + Style.NORMAL + Style.BRIGHT


def _reduce_events(events):
# FUTURE: Reduce ['a -> b', 'b -> c'] renames to ['a -> c']

creates = []
moves = []
for event, src, dest in events:
if event == FileCreatedEvent:
creates.append(dest)
if event == FileMovedEvent:
moves.append(dest)

seen = []
filtered = []
for event, src, dest in events:
# Skip 'modified' event during 'created'
if src in creates and event != FileCreatedEvent:
continue

# Skip 'modified' event during 'moved'
if src in moves:
continue

# Skip duplicate events
if src in seen:
continue
seen.append(src)

filtered.append((event, src, dest))
return filtered


def _bright(arg):
return STYLE_BRIGHT + arg + Style.RESET_ALL


def _highlight(arg):
return STYLE_HIGHLIGHT + arg + Style.RESET_ALL


def show_summary(argv, events, verbose=False):
command = ' '.join(argv)
bright = _bright
highlight = _highlight

time_stamp = time.strftime("%c", time.localtime(time.time()))
run_command_info = '[{}] Running: {}'.format(time_stamp,
highlight(command))
if not events:
print(run_command_info)
return

events = _reduce_events(events)
if verbose:
lines = ['Changes detected:']
m = max(map(len, map(lambda e: VERBOSE_EVENT_NAMES[e[0]], events)))
for event, src, dest in events:
event = VERBOSE_EVENT_NAMES[event].ljust(m)
lines.append(' {} {}'.format(
event,
highlight(src + (' -> ' + dest if dest else ''))))
lines.append('')
lines.append(run_command_info)
else:
lines = []
for event, src, dest in events:
lines.append('{} detected: {}'.format(
EVENT_NAMES[event],
bright(src + (' -> ' + dest if dest else ''))))
lines.append('')
lines.append(run_command_info)

print('\n'.join(lines))
Empty file added pytest_watch/tests/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions pytest_watch/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pytest


@pytest.fixture
def merge_config_callee(mocker):
m = mocker.patch("pytest_watch.command.merge_config",
side_effect=lambda *args, **kwargs: True)
return m


@pytest.fixture
def beep_mock(mocker):
return mocker.patch("pytest_watch.helpers.beep")


@pytest.fixture
def watch_callee(mocker):
watch_mock = mocker.patch("pytest_watch.command.watch")
watch_mock.return_value.side_effect = lambda *args, **kwargs: 0
return watch_mock
Loading