-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 92e15ee
Showing
6 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*~ | ||
*.py[co] | ||
*.egg-info | ||
/build/ | ||
/dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Fab Polish | ||
|
||
Run various checks against source code using Fabric | ||
|
||
## Installation | ||
|
||
`pip install fab-polish` | ||
|
||
## Usage | ||
|
||
### Minimal Usage | ||
|
||
Create a `fabfile.py` in your source code with the following minimal code: | ||
|
||
```python | ||
from fabpolish import polish | ||
from fabpolish.contrib import find_merge_conflict_leftovers | ||
``` | ||
|
||
Now run `fab polish`. The above example runs a sniff that finds bad merge | ||
commits by checking if symbols like '<<<<<<<' are present in the versioned | ||
files. | ||
|
||
### Writing Sniffs | ||
|
||
You can create your own sniff by using the sniff decorator: | ||
|
||
```python | ||
from fabpolish import polish, sniff, local, info | ||
|
||
@sniff(severity='critical', timing='fast') | ||
def check_var_dump(): | ||
info("Checking var_dump statements...") | ||
return local("! git grep 'var_dump'") | ||
``` | ||
|
||
Severity can be 'critical', 'major', 'minor', 'info'. Default is 'critical'. | ||
Timing can be 'slow', 'fast'. Default is 'fast'. | ||
|
||
When using default values, the sniff decorator can be used without the function | ||
call like so: | ||
|
||
```python | ||
@sniff | ||
def your_sniff(): | ||
# code | ||
``` | ||
|
||
Check https://github.com/practo/FabPolish/blob/master/fabpolish/contrib.py for more examples. | ||
|
||
### Modifying Imported Sniffs | ||
|
||
The severity, timing values can be altered for any sniff imported from contrib | ||
using `update_sniff` function like follows: | ||
|
||
```python | ||
from fabpolish import update_sniff | ||
from fabpolish.contrib import find_pep8_violations | ||
|
||
update_sniff(find_pep8_violations, severity='major', timing='fast') | ||
``` | ||
|
||
### Running All Sniffs | ||
|
||
By default `fab polish` runs only fast-critical and fast-major sniffs. In a CI | ||
environment, to run all the sniffs including slow, minor ones, run `fab polish:ci` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from fabpolish import polish, update_sniff | ||
from fabpolish.contrib import ( | ||
find_merge_conflict_leftovers, | ||
find_pep8_violations | ||
) | ||
|
||
update_sniff(find_pep8_violations, severity='major', timing='fast') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import os | ||
import sys | ||
|
||
from functools import wraps | ||
|
||
from fabric.api import lcd, local, settings, task, puts, hide | ||
from fabric.colors import green | ||
|
||
import fabfile | ||
|
||
FABFILE_DIR = os.path.abspath(os.path.dirname(fabfile.__file__)) | ||
|
||
__version__ = '1.0.0' | ||
|
||
|
||
def info(text): | ||
puts(green(text)) | ||
|
||
|
||
def validate_severity(severity): | ||
severity_options = ['critical', 'major', 'minor', 'info'] | ||
if severity not in severity_options: | ||
raise ValueError('severity must be one of: ' + str(severity_options)) | ||
|
||
|
||
def validate_timing(timing): | ||
timing_options = ['slow', 'fast'] | ||
if timing not in timing_options: | ||
raise ValueError('timing must be one of: ' + str(timing_options)) | ||
|
||
|
||
_sniffs = [] | ||
|
||
|
||
def sniff(*args, **kwargs): | ||
""" Decorator to collect sniffs and execute on polish | ||
:param severity: Keyword argument only. | ||
One of 'critical', 'major', 'minor', 'info' | ||
Default: 'critical' | ||
:type severity: str | ||
:param timing: Keyword argument only. One of 'slow', 'fast' | ||
Default: 'fast' | ||
:type timing: str | ||
""" | ||
DEFAULT_SEVERITY = 'critical' | ||
DEFAULT_TIMING = 'fast' | ||
invoked = bool(not args or kwargs) | ||
severity = kwargs.get('severity', DEFAULT_SEVERITY) | ||
timing = kwargs.get('timing', DEFAULT_TIMING) | ||
validate_severity(severity) | ||
validate_timing(timing) | ||
|
||
def decorator(func): | ||
@task | ||
@wraps(func) | ||
def wrapper(*args, **kwargs): | ||
with lcd(FABFILE_DIR), settings(hide('running')): | ||
return func(*args, **kwargs) | ||
_sniffs.append({ | ||
'severity': severity, | ||
'timing': timing, | ||
'function': wrapper | ||
}) | ||
return wrapper | ||
return decorator if invoked else decorator(args[0]) | ||
|
||
|
||
@task | ||
def polish(env='dev'): | ||
"""Polish code by running some or all sniffs | ||
:param env: Environment to determine what all sniffs to run | ||
Options: 'dev', 'ci' | ||
Default: 'dev' | ||
:type env: str | ||
When environment is 'ci', all the sniffs registered are run. | ||
When environment is 'dev', only fast-critical and fast-major | ||
sniffs are run. | ||
""" | ||
results = list() | ||
with settings(warn_only=True): | ||
if env == 'ci': | ||
sniffs_to_run = _sniffs | ||
elif env == 'dev': | ||
sniffs_to_run = [] | ||
for sniff in _sniffs: | ||
if sniff['timing'] != 'fast': | ||
continue | ||
if sniff['severity'] not in ('critical', 'major'): | ||
continue | ||
sniffs_to_run.append(sniff) | ||
else: | ||
raise ValueError('env must be one of: ' + str(['dev', 'ci'])) | ||
for sniff in sniffs_to_run: | ||
results.append(sniff['function']()) | ||
|
||
if any(result.failed for result in results): | ||
sys.exit(1) | ||
|
||
|
||
def update_sniff(function, severity=None, timing=None): | ||
if type(function) == str: | ||
function_name = function | ||
else: | ||
function_name = function.name | ||
for sniff in _sniffs: | ||
if sniff['function'].name == function_name: | ||
break | ||
else: | ||
raise ValueError('function is not a sniff or is not loaded') | ||
if severity is not None: | ||
validate_severity(severity) | ||
sniff['severity'] = severity | ||
if timing is not None: | ||
validate_timing(timing) | ||
sniff['timing'] = timing | ||
|
||
|
||
__all__ = [ | ||
'sniff', | ||
'info', | ||
'local', | ||
'polish', | ||
'update_sniff' | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from fabpolish import sniff, info, local | ||
|
||
|
||
@sniff(severity='critical', timing='fast') | ||
def find_merge_conflict_leftovers(): | ||
"""Find Merge conflict leftovers | ||
""" | ||
info('Finding merge conflict leftovers...') | ||
return local("! git grep -P '^(<|=|>){7}(?![<=>])'") | ||
|
||
|
||
@sniff(severity='major', timing='slow') | ||
def find_php_syntax_errors(): | ||
"""Find syntax error in php files | ||
""" | ||
info('Finding syntax error in php files...') | ||
return local( | ||
"git ls-files -z | " | ||
"grep -PZz '\.(php|phtml)$' | " | ||
"xargs -0 -n 1 php -l >/tmp/debug" | ||
) | ||
|
||
|
||
@sniff(severity='minor', timing='slow') | ||
def find_pep8_violations(): | ||
"""Run pep8 python coding standard check | ||
""" | ||
info('Running coding standards check for python files...') | ||
return local( | ||
"git ls-files -z | " | ||
"grep -PZz '\.py$' | " | ||
"xargs -0 pep8" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from setuptools import setup | ||
|
||
setup(name='fab-polish', | ||
version='1.0.0', | ||
description='Polish git versioned source code using Fabric', | ||
url='https://github.com/practo/FabPolish', | ||
author='J Kishore Kumar', | ||
author_email='kishore@practo.com', | ||
license='MIT', | ||
packages=['fabpolish'], | ||
install_requires=[ | ||
'fabric', | ||
], | ||
zip_safe=False) |