WSCheck¶
WSCheck is a static analysis tool for whitespaces.
Installation¶
$ pip install wscheck
Usage¶
Check multiple files:
$ wscheck orange.sh pineapple.xml kiwi.js
Exclude rules:
$ wscheck --exclude WSC002 --exclude WSC003 orange.sh
Get list of available rules:
$ wscheck --list-rules
For details about rules, see Rules
Write CheckStyle output too:
$ wscheck --checkstyle results.xml pineapple.xml
Example¶
$ wscheck examples/multiple_problems.py
In examples/multiple_problems.py line 2:
class LabelPrinter:
^-- WSC007: File begins with newline
In examples/multiple_problems.py line 6:
self.print_to_pdf()
^-- WSC002: Tailing whitespace
In examples/multiple_problems.py line 9:
def __generate_pdf(self):
^-- WSC003: Indentation is not multiple of 2
In examples/multiple_problems.py line 10:
pdf_generator = _LabelPdfGenerator()
^-- WSC001: Bad line ending '\r\n'
In examples/multiple_problems.py line 16:
--->--->os.makedirs(self.__cache_dir, exist_ok=True)
^-- WSC004: Indentation with non-space character
In examples/multiple_problems.py line 22:
return os.path.join(self.__cache_dir, pdf_name)
^-- WSC006: Too many newline at end of file (+1)
Bugs¶
Bugs or suggestions? Visit the issue tracker.
Benchmark¶
You can run a quick benchmark:
tox -- tests/performance --quick-benchmark
You can run benchmarks and generate histogram for compare calls to each other:
tox -- tests/performance --benchmark-histogram
You can run benchmarks and save results for later compare:
tox -- tests/performance --benchmark-save=foo
You can run benchmarks and compare with the last saved result with fail treshold:
tox -- tests/performance --benchmark-histogram --benchmark-compare --benchmark-compare-fail=mean:5% --benchmark-sort=name
You can run benchmarks and compare with the last saved result by groups:
tox -- tests/performance --benchmark-histogram --benchmark-compare --benchmark-group-by=func tox -- tests/performance --benchmark-histogram --benchmark-compare --benchmark-group-by=name
Topics¶
Rules¶
WSC001: Bad line ending¶
This rule enforces Linux style (\n
) line ending, and alerting for Windows (\r\n
) and Osx (\r
) style.
Example¶
Input file: examples/WSC001_bad_eol.py
class LabelPrinter:
def __generate_pdf(self):
pdf_generator = _LabelPdfGenerator()
pdf_generator.generate_label(
self.__title, self.__data, self.__logo_path, config.App.LABEL_BORDER,
output_path=self.__pdf_path)
Command:
$ wscheck 'examples/WSC001_bad_eol.py'
In examples/WSC001_bad_eol.py line 3:
pdf_generator = _LabelPdfGenerator()
^-- WSC001: Bad line ending '\r\n'
In examples/WSC001_bad_eol.py line 5:
self.__title, self.__data, self.__logo_path, config.App.LABEL_BORDER,
^-- WSC001: Bad line ending '\r'
WSC002: Tailing whitespace¶
Alerting for left spaces, tabulators at end of lines.
Example¶
Input file: examples/WSC002_tailing_ws.py
class LabelPrinter:
def print(self, printer: (Printer, None)=None, copies: int=1):
printer = printer or Printer(config.App.LABEL_PRINTER)
self.print_to_pdf()
printer.print_pdf(self.__pdf_path, options={'copies': str(copies)})
Command:
$ wscheck 'examples/WSC002_tailing_ws.py'
In examples/WSC002_tailing_ws.py line 3:
printer = printer or Printer(config.App.LABEL_PRINTER)
^-- WSC002: Tailing whitespace
In examples/WSC002_tailing_ws.py line 5:
self.print_to_pdf()
^-- WSC002: Tailing whitespace
WSC003: Indentation is not multiple of 2¶
This rule alerting for indentation (whitespaces before the line) must be multiple of 2 spaces (or zero).
Example¶
Input file: examples/WSC003_bad_indentation.py
class LabelPrinter:
def __generate_pdf(self):
pdf_generator = _LabelPdfGenerator()
pdf_generator.generate_label(
self.__title, self.__data, self.__logo_path, config.App.LABEL_BORDER,
output_path=self.__pdf_path)
Command:
$ wscheck 'examples/WSC003_bad_indentation.py'
In examples/WSC003_bad_indentation.py line 2:
def __generate_pdf(self):
^-- WSC003: Indentation is not multiple of 2
WSC004: Indentation with non-space character¶
This rule enforces the space indentation (whitespaces before the line can be spaces only).
Example¶
Input file: examples/WSC004_tab_indentation.py
class LabelPrinter:
def __prepare_print_cache_dir(self):
os.makedirs(self.__print_cache_dir, exist_ok=True)
Command:
$ wscheck 'examples/WSC004_tab_indentation.py'
In examples/WSC004_tab_indentation.py line 3:
--->--->os.makedirs(self.__print_cache_dir, exist_ok=True)
^-- WSC004: Indentation with non-space character
WSC005: No newline at end of file¶
This rule enforces one \n
at end of file.
Example¶
Input file: examples/WSC005_no_new_line_at_eof.py
class LabelPrinter:
def print(self, printer: (Printer, None)=None, copies: int=1):
printer = printer or Printer(config.App.LABEL_PRINTER)
self.print_to_pdf()
printer.print_pdf(self.__pdf_path, options={'copies': str(copies)})
Command:
$ wscheck 'examples/WSC005_no_new_line_at_eof.py'
In examples/WSC005_no_new_line_at_eof.py line 6:
printer.print_pdf(self.__pdf_path, options={'copies': str(copies)})
^-- WSC005: No newline at end of file
WSC006: Too many newlines at the end of file¶
This rule enforces one \n
at end of file.
Example¶
Input file: examples/WSC006_too_many_new_lines_at_eof.py
class LabelPrinter:
def __get_pdf_path(self) -> str:
pdf_name = self.__pdf_name_template.format(
data=self.__data,
title_hash=hashlib.sha1(self.__title.encode()).hexdigest())
return os.path.join(self.__print_cache_dir, pdf_name)
Command:
$ wscheck 'examples/WSC006_too_many_new_lines_at_eof.py'
In examples/WSC006_too_many_new_lines_at_eof.py line 6:
return os.path.join(self.__print_cache_dir, pdf_name)
^-- WSC006: Too many newline at end of file (+1)
WSC007: File begins with newline¶
Check empty lines before the first non-empty line.
Example¶
Input file: examples/WSC007_new_line_at_bof.py
class LabelPrinter:
def print(self, printer: (Printer, None)=None, copies: int=1):
printer = printer or Printer(config.App.LABEL_PRINTER)
self.print_to_pdf()
printer.print_pdf(self.__pdf_path, options={'copies': str(copies)})
Command:
$ wscheck 'examples/WSC007_new_line_at_bof.py'
In examples/WSC007_new_line_at_bof.py line 2:
class LabelPrinter:
^-- WSC007: File begins with newline
Contributing¶
Extending rules¶
Checklist¶
Extend the RULES list in
wscheck/checker.py
file with the next IDWrite unit tests and production code with TDD
- Extend the
tests/unit/checker/test_rules.py
file with specific unit tests. - Write the checker in
wscheck/checker.py
file. - Extend the complex cases with the new rule related things.
- Extend the
Extend performance tests in
tests/performance/test_checker_performance.py
- With a rule specific suite.
- Extend the complex case too.
- Run all performance tests for check performance degradation!
Extend documentation
- Create
docs/rules/WSC000.rst
file for describing the rule. - Write example into
examples/WSC000_foo
and use it in the.rst
. - Extend
examples/multiple_problems.py
file with a typical wrong line for demonstrate. - Refresh the output in
README.rst
too.
- Create
Update changelog
- Extend the link list of rules at the bottom of
CHANGELOG.md
. - Update the Unreleased section of
CHANGELOG.md
, where refers to the rule.
- Extend the link list of rules at the bottom of
Release¶
Checklist for release a new version¶
Update the
CHANGELOG.md
- Move all notes from Unreleased section to a new one with version and date.
- Copy and update(!) the diff link for the specified version and the Unreleaed too.
Update version in
wscheck/version.py
fileRun tests with CI
- Push changes of
devel
to remote - wait for the results of CI
- Push changes of
Check the package building
- Remove up the
build
directory - Build a package with
setup.py build
- Check the package contains in the new
build
directory
- Remove up the
If all tests are green, lets merge
- Merge
devel
branch with--no-ff
- Tag the merge patch
- Push them all
- Merge
Publish
- Check do you are on the tagged patch
- Build and upload package to pypi with
setup.py release
- Update tag description on GitHub