-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reorganize __main__ to have fewer responsibilities
- Loading branch information
Showing
2 changed files
with
170 additions
and
146 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 |
---|---|---|
@@ -1,158 +1,17 @@ | ||
""" | ||
Usage: | ||
squabble [options] [PATHS...] | ||
squabble (-h | --help) | ||
Arguments: | ||
PATHS Files or directories to lint. If given a directory, will | ||
recursively traverse the path and lint all files ending | ||
in `.sql` | ||
Options: | ||
-c --config=PATH Path to configuration file | ||
-h --help Show this screen | ||
-p --preset=PRESET Start with a base preset rule configuration | ||
-P --list-presets List the available preset configurations | ||
-r --show-rule=RULE Show detailed information about RULE | ||
-R --list-rules Print out information about all available rules | ||
-V --verbose Turn on debug level logging | ||
-v --version Show version information | ||
""" | ||
|
||
import glob | ||
import json | ||
import os.path | ||
import sys | ||
from pkg_resources import get_distribution | ||
|
||
import colorama | ||
import docopt | ||
from colorama import Style | ||
|
||
import squabble | ||
from squabble import config, lint, logger, rule, reporter | ||
from squabble import cli | ||
|
||
|
||
def main(): | ||
version = get_distribution('squabble').version | ||
args = docopt.docopt(__doc__, version=version) | ||
|
||
if args['--verbose']: | ||
logger.setLevel('DEBUG') | ||
|
||
paths = args['PATHS'] | ||
preset = args['--preset'] | ||
|
||
if args['--list-presets']: | ||
return list_presets() | ||
|
||
config_file = args['--config'] or config.discover_config_location() | ||
if config_file and not os.path.exists(config_file): | ||
sys.exit('%s: no such file or directory' % config_file) | ||
|
||
base_config = config.load_config(config_file, preset) | ||
|
||
# Load all of the rule classes into memory | ||
rule.load_rules(plugin_paths=base_config.plugins) | ||
|
||
if args['--list-rules']: | ||
return list_rules() | ||
elif args['--show-rule']: | ||
return show_rule(name=args['--show-rule']) | ||
|
||
files = collect_files(paths) | ||
|
||
issues = [] | ||
for file_name in files: | ||
issues += lint_file(base_config, file_name) | ||
|
||
reporter.report(base_config.reporter, issues) | ||
|
||
# Make sure we have an error status if something went wrong. | ||
if issues: | ||
sys.exit(1) | ||
|
||
|
||
def lint_file(base_config, file_name): | ||
file_config = config.apply_file_config(base_config, file_name) | ||
return lint.check_file(file_config, file_name) | ||
|
||
|
||
def collect_files(paths): | ||
""" | ||
Given a list of files or directories, return all named files as well as | ||
any files ending in `.sql` in the directories. | ||
""" | ||
files = [] | ||
|
||
for path in map(os.path.expanduser, paths): | ||
if not os.path.exists(path): | ||
sys.exit('%s: no such file or directory' % path) | ||
|
||
elif os.path.isdir(path): | ||
sql = os.path.join(path, '**/*.sql') | ||
files.extend(glob.iglob(sql, recursive=True)) | ||
|
||
else: | ||
files.append(path) | ||
|
||
return files | ||
|
||
|
||
def show_rule(name): | ||
"""Print information about rule named ``name``.""" | ||
color = { | ||
'bold': Style.BRIGHT, | ||
'reset': Style.RESET_ALL, | ||
} | ||
|
||
try: | ||
meta = rule.Registry.get_meta(name) | ||
except squabble.UnknownRuleException: | ||
sys.exit('{bold}Unknown rule:{reset} {name}'.format(**{ | ||
'name': name, | ||
**color | ||
})) | ||
|
||
print('{bold}{name}{reset} - {description}\n{help}'.format(**{ | ||
**meta, | ||
**color | ||
})) | ||
|
||
|
||
def list_rules(): | ||
"""Print out all registered rules and brief description of what they do.""" | ||
color = { | ||
'bold': Style.BRIGHT, | ||
'reset': Style.RESET_ALL, | ||
} | ||
|
||
all_rules = sorted(rule.Registry.all(), key=lambda r: r['name']) | ||
|
||
for meta in all_rules: | ||
print('{bold}{name: <32}{reset} {description}'.format(**{ | ||
**color, | ||
**meta | ||
})) | ||
|
||
|
||
def list_presets(): | ||
"""Print out all the preset configurations.""" | ||
for name, preset in config.PRESETS.items(): | ||
print('{bold}{name}{reset} - {description}'.format( | ||
name=name, | ||
description=preset.get('description', ''), | ||
bold=Style.BRIGHT, | ||
reset=Style.RESET_ALL | ||
)) | ||
colorama.init() | ||
status = cli.main() | ||
|
||
# npm here i come | ||
left_pad = ' ' | ||
cfg = json.dumps(preset['config'], indent=4)\ | ||
.replace('\n', '\n' + left_pad) | ||
print(left_pad + cfg) | ||
if status: | ||
sys.exit(status) | ||
|
||
|
||
if __name__ == '__main__': | ||
colorama.init() | ||
main() |
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,165 @@ | ||
""" | ||
Usage: | ||
squabble [options] [PATHS...] | ||
squabble (-h | --help) | ||
Arguments: | ||
PATHS Files or directories to lint. If given a directory, will | ||
recursively traverse the path and lint all files ending | ||
in `.sql` | ||
Options: | ||
-c --config=PATH Path to configuration file | ||
-h --help Show this screen | ||
-p --preset=PRESET Start with a base preset rule configuration | ||
-P --list-presets List the available preset configurations | ||
-r --show-rule=RULE Show detailed information about RULE | ||
-R --list-rules Print out information about all available rules | ||
-V --verbose Turn on debug level logging | ||
-v --version Show version information | ||
""" | ||
|
||
import glob | ||
import json | ||
import os.path | ||
import sys | ||
from pkg_resources import get_distribution | ||
|
||
import docopt | ||
from colorama import Style | ||
|
||
import squabble | ||
from squabble import config, lint, logger, rule, reporter | ||
|
||
|
||
def main(): | ||
version = get_distribution('squabble').version | ||
args = docopt.docopt(__doc__, version=version) | ||
return dispatch_args(args) | ||
|
||
|
||
def dispatch_args(args): | ||
""" | ||
Handle the command line arguments as parsed by ``docopt``. Calls the | ||
subroutine implied by the combination of command line flags and returns the | ||
exit status (or ``None``, if successful) of the program. | ||
Note that some exceptional conditions will terminate the program directly. | ||
""" | ||
if args['--verbose']: | ||
logger.setLevel('DEBUG') | ||
|
||
if args['--list-presets']: | ||
return list_presets() | ||
|
||
config_file = args['--config'] or config.discover_config_location() | ||
if config_file and not os.path.exists(config_file): | ||
sys.exit('%s: no such file or directory' % config_file) | ||
|
||
base_config = config.load_config(config_file, preset_name=args['--preset']) | ||
|
||
# Load all of the rule classes into memory (need to do this now to | ||
# be able to list all rules / show rule details) | ||
rule.load_rules(plugin_paths=base_config.plugins) | ||
|
||
if args['--list-rules']: | ||
return list_rules() | ||
|
||
if args['--show-rule']: | ||
return show_rule(name=args['--show-rule']) | ||
|
||
return run_linter(base_config, args['PATHS']) | ||
|
||
|
||
def run_linter(base_config, paths): | ||
""" | ||
Run linter against all SQL files contained in ``paths``. | ||
``paths`` may contain both files and directories. | ||
""" | ||
files = collect_files(paths) | ||
|
||
issues = [] | ||
for file_name in files: | ||
file_config = config.apply_file_config(base_config, file_name) | ||
issues += lint.check_file(file_config, file_name) | ||
|
||
reporter.report(base_config.reporter, issues) | ||
|
||
# Make sure we have an error status if something went wrong. | ||
return 1 if len(issues) > 0 else 0 | ||
|
||
|
||
def collect_files(paths): | ||
""" | ||
Given a list of files or directories, return all named files as well as | ||
any files ending in `.sql` in the directories. | ||
""" | ||
files = [] | ||
|
||
for path in map(os.path.expanduser, paths): | ||
if not os.path.exists(path): | ||
sys.exit('%s: no such file or directory' % path) | ||
|
||
elif os.path.isdir(path): | ||
sql = os.path.join(path, '**/*.sql') | ||
files.extend(glob.iglob(sql, recursive=True)) | ||
|
||
else: | ||
files.append(path) | ||
|
||
return files | ||
|
||
|
||
def show_rule(name): | ||
"""Print information about rule named ``name``.""" | ||
color = { | ||
'bold': Style.BRIGHT, | ||
'reset': Style.RESET_ALL, | ||
} | ||
|
||
try: | ||
meta = rule.Registry.get_meta(name) | ||
except squabble.UnknownRuleException: | ||
sys.exit('{bold}Unknown rule:{reset} {name}'.format(**{ | ||
'name': name, | ||
**color | ||
})) | ||
|
||
print('{bold}{name}{reset} - {description}\n{help}'.format(**{ | ||
**meta, | ||
**color | ||
})) | ||
|
||
|
||
def list_rules(): | ||
"""Print out all registered rules and brief description of what they do.""" | ||
color = { | ||
'bold': Style.BRIGHT, | ||
'reset': Style.RESET_ALL, | ||
} | ||
|
||
all_rules = sorted(rule.Registry.all(), key=lambda r: r['name']) | ||
|
||
for meta in all_rules: | ||
print('{bold}{name: <32}{reset} {description}'.format(**{ | ||
**color, | ||
**meta | ||
})) | ||
|
||
|
||
def list_presets(): | ||
"""Print out all the preset configurations.""" | ||
for name, preset in config.PRESETS.items(): | ||
print('{bold}{name}{reset} - {description}'.format( | ||
name=name, | ||
description=preset.get('description', ''), | ||
bold=Style.BRIGHT, | ||
reset=Style.RESET_ALL | ||
)) | ||
|
||
# npm here i come | ||
left_pad = ' ' | ||
cfg = json.dumps(preset['config'], indent=4)\ | ||
.replace('\n', '\n' + left_pad) | ||
print(left_pad + cfg) |