Skip to content

Commit

Permalink
Add enum for LintIssue severity
Browse files Browse the repository at this point in the history
  • Loading branch information
erik committed Jan 4, 2019
1 parent 7785305 commit f9e9c96
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
4 changes: 3 additions & 1 deletion docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ Example Rule
.. code-block:: python
import squabble.rule
from squabble.lint import Severity
from squabble.message import Message
from squabble.rules import BaseRule
Expand Down Expand Up @@ -193,4 +194,5 @@ Example Rule
# Report an error if this table was not SCREAMING_CASE
ctx.report(
self.TableNotLoudEnough(name=table_name),
node=node.relation)
node=node.relation,
severity=Severity.HIGH)
26 changes: 23 additions & 3 deletions squabble/lint.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
""" linting engine """

import collections
import enum

import pglast

from squabble.rules import Registry

_LintIssue = collections.namedtuple('LintIssue', [
_LintIssue = collections.namedtuple('_LintIssue', [
'message',
'message_text',
'node',
Expand All @@ -23,6 +24,21 @@ class LintIssue(_LintIssue):
pass


class Severity(enum.Enum):
"""
Enumeration describing the relative severity of a :class:`~LintIssue`.
By themselves, these values don't mean much, but are meant to
convey the likely hood that a detected issue is truly
problematic. For example, a syntax error in a migration would be
``CRITICAL``, but perhaps a naming inconsistency would be ``LOW``.
"""
LOW = 'LOW'
MEDIUM = 'MEDIUM'
HIGH = 'HIGH'
CRITICAL = 'CRITICAL'


def _parse_string(text):
"""Use ``pglast`` to turn ``text`` into a SQL AST."""
return pglast.Node(pglast.parse_sql(text))
Expand Down Expand Up @@ -69,6 +85,10 @@ def report_issue(self, issue):
self._issues.append(i)

def lint(self):
"""
Run the linter on SQL given in constructor, returning a list of
:class:`~LintIssue` discovered.
"""
root_ctx = Context(self)

for rule, config in self._rules:
Expand All @@ -80,7 +100,7 @@ def lint(self):

except pglast.parser.ParseError as exc:
root_ctx.report_issue(LintIssue(
severity='ERROR',
severity=Severity.CRITICAL,
message_text=exc.args[0],
location=exc.location
))
Expand Down Expand Up @@ -170,7 +190,7 @@ def report(self, message, node=None, severity=None):
self.report_issue(LintIssue(
message=message,
node=node,
severity=severity or 'ERROR',
severity=severity or Severity.MEDIUM,
# This is filled in later
file=None,
))
23 changes: 19 additions & 4 deletions squabble/reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from colorama import Fore, Style

import squabble
from squabble.lint import Severity

_REPORTERS = {}

Expand Down Expand Up @@ -126,21 +127,22 @@ def _issue_info(issue, file_contents):
formatted = _format_message(issue)

return {
**issue._asdict(),
**(issue.message.asdict() if issue.message else {}),
'line_text': line,
'line': line_num,
'column': column,
'message_formatted': formatted,
**issue._asdict(),
**(issue.message.asdict() if issue.message else {})
'severity': issue.severity.name,
}


_SIMPLE_FORMAT = '{file}:{line}:{column} {severity}: {message_formatted}'

# Partially pre-format the message since the color codes will be static.
_COLOR_FORMAT = '{bold}{{file}}:{reset}{{line}}:{{column}}{reset} '\
'{red}{{severity}}{reset}: {{message_formatted}}'\
.format(bold=Style.BRIGHT, red=Fore.RED, reset=Style.RESET_ALL)
'{{severity}} {{message_formatted}}'\
.format(bold=Style.BRIGHT, reset=Style.RESET_ALL)


@reporter("plain")
Expand All @@ -152,13 +154,26 @@ def plain_text_reporter(issue, file_contents):
]


_SEVERITY_COLOR = {
Severity.CRITICAL: Fore.RED,
Severity.HIGH: Fore.RED,
Severity.MEDIUM: Fore.YELLOW,
Severity.LOW: Fore.BLUE,
}


@reporter('color')
def color_reporter(issue, file_contents):
"""
Extension of :func:`squabble.reporter.plain_text_reporter`, uses
ANSI color and shows error location.
"""
info = _issue_info(issue, file_contents)
info['severity'] = '{color}{severity}{reset}'.format(
color=_SEVERITY_COLOR[issue.severity],
severity=issue.severity.name,
reset=Style.RESET_ALL
)

output = [_COLOR_FORMAT.format(**info)]

Expand Down

0 comments on commit f9e9c96

Please sign in to comment.