blob: 84614ef95f08393fdf4a3ba17fe4b2efa37324fc [file] [log] [blame]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# nosy: continuous integration for watchdog
#
# Copyright (C) 2010 Gora Khargosh <gora.khargosh@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
:module: nosy
:synopsis: Rewrite of Jeff Winkler's nosy script tailored to testing watchdog
:platform: OS-independent
"""
import os.path
import sys
import stat
import time
import subprocess
from fnmatch import fnmatch
def match_patterns(pathname, patterns):
"""Returns ``True`` if the pathname matches any of the given patterns."""
for pattern in patterns:
if fnmatch(pathname, pattern):
return True
return False
def filter_paths(pathnames, patterns=None, ignore_patterns=None):
"""Filters from a set of paths based on acceptable patterns and
ignorable patterns."""
result = []
if patterns is None:
patterns = ['*']
if ignore_patterns is None:
ignore_patterns = []
for pathname in pathnames:
if match_patterns(pathname, patterns) and not match_patterns(pathname, ignore_patterns):
result.append(pathname)
return result
def absolute_walker(pathname, recursive):
if recursive:
walk = os.walk
else:
def walk(_path):
try:
return next(os.walk(_path))
except NameError:
return os.walk(_path).next()
for root, directories, filenames in walk(pathname):
yield root
for directory in directories:
yield os.path.abspath(os.path.join(root, directory))
for filename in filenames:
yield os.path.abspath(os.path.join(root, filename))
def glob_recursive(pathname, patterns=None, ignore_patterns=None):
full_paths = []
for root, _, filenames in os.walk(pathname):
for filename in filenames:
full_path = os.path.abspath(os.path.join(root, filename))
full_paths.append(full_path)
filepaths = filter_paths(full_paths, patterns, ignore_patterns)
return filepaths
def check_sum(pathname='.', patterns=None, ignore_patterns=None):
checksum = 0
for f in glob_recursive(pathname, patterns, ignore_patterns):
stats = os.stat(f)
checksum += stats[stat.ST_SIZE] + stats[stat.ST_MTIME]
return checksum
if __name__ == "__main__":
if len(sys.argv) > 1:
path = sys.argv[1]
else:
path = '.'
if len(sys.argv) > 2:
command = sys.argv[2]
else:
commands = [
# Build documentation automatically as well as the source code
# changes.
"make SPHINXBUILD=../bin/sphinx-build -C docs html",
# The reports coverage generates all by itself are more
# user-friendly than the ones which `nosetests --with-coverage`
# generates. Therefore, we call `coverage` explicitly to
# generate reports, and to keep the reports in synchronization
# with the source code, we erase all coverage information
# before regenerating reports or running `nosetests`.
"bin/coverage erase",
"bin/python-tests tests/run_tests.py",
"bin/coverage html",
]
command = '; '.join(commands)
previous_checksum = 0
while True:
calculated_checksum = check_sum(path, patterns=['*.py', '*.rst', '*.rst.inc'])
if calculated_checksum != previous_checksum:
previous_checksum = calculated_checksum
subprocess.Popen(command, shell=True)
time.sleep(2)