def test__linter__path_from_paths__file(): """Test extracting paths from a file path.""" lntr = Linter(config=FluffConfig()) paths = lntr.paths_from_path('test/fixtures/linter/indentation_errors.sql') assert normalise_paths(paths) == { 'test.fixtures.linter.indentation_errors.sql' }
def test__linter__lint_string_vs_file(path): """Test the linter finds the same things on strings and files.""" with open(path, 'r') as f: sql_str = f.read() lntr = Linter(config=FluffConfig()) assert (lntr.lint_string(sql_str).check_tuples() == lntr.lint_path( path).check_tuples())
def assert_rule_fail_in_sql(code, sql, configs=None): """Assert that a given rule does fail on the given sql.""" # Configs allows overrides if we want to use them. cfg = FluffConfig(configs=configs) r = get_rule_from_set(code, config=cfg) parsed, _, _ = Linter(config=cfg).parse_string(sql) print("Parsed:\n {0}".format(parsed.stringify())) lerrs, _, _, _ = r.crawl(parsed, dialect=cfg.get('dialect_obj'), fix=True) print("Errors Found: {0}".format(lerrs)) assert any(v.rule.code == code for v in lerrs) fixed = parsed # use this as our buffer (yes it's a bit of misnomer right here) while True: # We get the errors again, but this time skip the assertion # because we're in the loop. If we asserted on every loop then # we're stuffed. lerrs, _, _, _ = r.crawl(fixed, dialect=cfg.get('dialect_obj'), fix=True) print("Errors Found: {0}".format(lerrs)) fixes = [] for e in lerrs: fixes += e.fixes if not fixes: print("Done") break print("Fixes to apply: {0}".format(fixes)) l_fixes = fixes # Save the fixes to compare to later fixed, fixes = fixed.apply_fixes(fixes) # iterate until all fixes applied if fixes: if fixes == l_fixes: raise RuntimeError( "Fixes aren't being applied: {0!r}".format(fixes)) return fixed.raw
def test__linter__lint_file_operators_negative(): lntr = Linter() f = StringIO( u"SELECT\n a - b as c,\n -2 as d\n a - b as e\nFROM tbl\n") lnt = lntr.lint_file(f) violations = lnt.check_tuples() # Check we only get one violation and it's the first assert violations == [('L006', 2, 7)]
def test__linter__path_from_paths__ignore(path): """Test extracting paths from a dot.""" lntr = Linter(config=FluffConfig()) paths = lntr.paths_from_path(path) # We should only get query_b, because of the sqlfluffignore files. assert normalise_paths(paths) == { 'test.fixtures.linter.sqlfluffignore.path_b.query_b.sql' }
def test__linter__lint_file_operators_star(): """ Test the exception to the operator rule, allowing a star in brackets """ lntr = Linter() f = StringIO(u"SELECT COUNT(*) FROM tbl") lnt = lntr.lint_file(f) violations = lnt.check_tuples() # Check that this is allowed assert violations == []
def test__dialect__ansi_specific_segment_not_parse(raw, err_locations, caplog): """Test queries do not parse, with parsing errors raised properly.""" config = FluffConfig(overrides=dict(dialect='ansi')) lnt = Linter(config=config) _, vs, _ = lnt.parse_string(raw) assert len(vs) > 0 locs = [(v.line_no(), v.line_pos()) for v in vs] assert locs == err_locations
def test__linter__path_from_paths_dot(): lntr = Linter() paths = lntr.paths_from_path('.') # Use set theory to check that we get AT LEAST these files assert normalise_paths(paths) >= set([ 'test.fixtures.lexer.block_comment.sql', 'test.fixtures.lexer.inline_comment.sql', 'test.fixtures.lexer.basic.sql' ])
def test__linter__path_from_paths__dir(): """Test extracting paths from directories.""" lntr = Linter(config=FluffConfig()) paths = lntr.paths_from_path('test/fixtures/lexer') assert normalise_paths(paths) == { 'test.fixtures.lexer.block_comment.sql', 'test.fixtures.lexer.inline_comment.sql', 'test.fixtures.lexer.basic.sql' }
def test__linter__path_from_paths__dir(): lntr = Linter() paths = lntr.paths_from_path('test/fixtures/lexer') # NB This test might fail on Linux or Mac - should probably correct... assert normalise_paths(paths) == set([ 'test.fixtures.lexer.block_comment.sql', 'test.fixtures.lexer.inline_comment.sql', 'test.fixtures.lexer.basic.sql' ])
def test__rules__std_file(rule, path, violations): """Test the linter finds the given errors in (and only in) the right places.""" # Use config to look for only the rule we care about. lntr = Linter(config=FluffConfig(overrides=dict(rules=rule))) lnt = lntr.lint_path(path) # Reformat the test data to match the format we're expecting. We use # sets because we really don't care about order and if one is missing, # we don't care about the orders of the correct ones. assert set(lnt.check_tuples()) == {(rule, v[0], v[1]) for v in violations}
def test__linter__path_from_paths__dot(): """Test extracting paths from a dot.""" lntr = Linter(config=FluffConfig()) paths = lntr.paths_from_path('.') # Use set theory to check that we get AT LEAST these files assert normalise_paths(paths) >= { 'test.fixtures.lexer.block_comment.sql', 'test.fixtures.lexer.inline_comment.sql', 'test.fixtures.lexer.basic.sql' }
def test__linter__lint_file_operators(): lntr = Linter() lnt = lntr.lint_path('test/fixtures/linter/operator_errors.sql') # Check the Num violations command while we're here assert lnt.num_violations() == 3 violations = lnt.check_tuples() # Check we get comma whitespace errors assert ('L006', 3, 9) in violations assert ('L006', 4, 8) in violations assert ('L007', 5, 8) in violations
def assert_rule_pass_in_sql(code, sql, configs=None): """Assert that a given rule doesn't fail on the given sql.""" # Configs allows overrides if we want to use them. cfg = FluffConfig(configs=configs) r = get_rule_from_set(code, config=cfg) parsed, _, _ = Linter(config=cfg).parse_string(sql) print("Parsed:\n {0}".format(parsed.stringify())) lerrs, _, _, _ = r.crawl(parsed, dialect=cfg.get('dialect_obj'), fix=True) print("Errors Found: {0}".format(lerrs)) assert not any(v.rule.code == code for v in lerrs)
def test__linter__lint_file_operators_paths(): """ Same as the above test, but called via lint_paths """ lntr = Linter() lnt = lntr.lint_paths(['test/fixtures/linter/operator_errors.sql']) # Check the Num violations command while we're here assert lnt.num_violations() == 3 violations = lnt.check_tuples() # Check we get comma whitespace errors assert ('L006', 3, 9) in violations assert ('L006', 4, 8) in violations assert ('L007', 5, 8) in violations
def assert_structure(yaml_loader, path, code_only=True): """Check that a parsed sql file matches the yaml file with the same name.""" lntr = Linter(config=FluffConfig()) p = list(lntr.parse_path(path + '.sql')) parsed = p[0][0] if parsed is None: print(p) raise RuntimeError(p[0][1]) # Whitespace is important here to test how that's treated tpl = parsed.to_tuple(code_only=code_only, show_raw=True) expected = yaml_loader(path + '.yml') assert tpl == expected
def test__linter__lint_file_whitespace(): lntr = Linter() lnt = lntr.lint_path('test/fixtures/linter/whitespace_errors.sql') violations = lnt.check_tuples() # Check we get comma (with leading space) whitespace errors # assert ('L005', 2, 8) in violations # assert ('L005', 4, 0) in violations # Check we get comma (with incorrect trailing space) whitespace errors assert ('L008', 3, 12) in violations # Check for no false positives on line 4 or 5 assert not any([v[0] == 'L008' and v[1] == 4 for v in violations]) assert not any([v[1] == 5 for v in violations])
def test__linter__lint_file_indentation(): lntr = Linter() lnt = lntr.lint_path('test/fixtures/linter/indentation_errors.sql') violations = lnt.check_tuples() # Check we get the trialing whitespace violation assert ('L001', 4, 24) in violations # Check we get the mixed indentation errors assert ('L002', 3, 1) in violations assert ('L002', 4, 1) in violations # Check we get the space multiple violations assert ('L003', 3, 1) in violations # Check we get the mixed indentation errors between lines assert ('L004', 5, 1) in violations
def test__config__nested_config_tests(): """Test linting with overriden config in nested paths. This looks like a linter test but it's actually a config test. """ lntr = Linter(config=FluffConfig(overrides=dict(exclude_rules='L002'))) lnt = lntr.lint_path('test/fixtures/config/inheritance_b') violations = lnt.check_tuples(by_path=True) for k in violations: if k.endswith('nested\\example.sql'): assert ('L003', 1, 4) in violations[k] assert ('L009', 1, 12) in violations[k] assert 'L002' not in [c[0] for c in violations[k]] elif k.endswith('inheritance_b\\example.sql'): assert ('L003', 1, 4) in violations[k] assert 'L002' not in [c[0] for c in violations[k]] assert 'L009' not in [c[0] for c in violations[k]]
def auto_fix_test(rules, dialect, folder): """A test for roundtrip testing, take a file buffer, lint, fix and lint. This is explicitly different from the linter version of this, in that it uses the command line rather than the direct api. """ filename = 'testing.sql' # Lets get the path of a file to use tempdir_path = tempfile.mkdtemp() filepath = os.path.join(tempdir_path, filename) cfgpath = os.path.join(tempdir_path, '.sqlfluff') src_filepath = os.path.join(*base_auto_fix_path, dialect, folder, 'before.sql') cmp_filepath = os.path.join(*base_auto_fix_path, dialect, folder, 'after.sql') vio_filepath = os.path.join(*base_auto_fix_path, dialect, folder, 'violations.json') cfg_filepath = os.path.join(*base_auto_fix_path, dialect, folder, '.sqlfluff') # Open the example file and write the content to it print_buff = '' with open(filepath, mode='w') as dest_file: with open(src_filepath, mode='r') as source_file: for line in source_file: dest_file.write(line) print_buff += line # Copy the config file too try: with open(cfgpath, mode='w') as dest_file: with open(cfg_filepath, mode='r') as source_file: for line in source_file: dest_file.write(line) except FileNotFoundError: # No config file? No biggie pass print("## Input file:\n{0}".format(print_buff)) # Do we need to do a violations check? try: with open(vio_filepath, mode='r') as vio_file: violations = json.load(vio_file) except FileNotFoundError: # No violations file. Let's not worry violations = None # Run the fix command cfg = FluffConfig.from_root(overrides=dict(rules=rules, dialect=dialect)) lnt = Linter(config=cfg, output_func=lambda m: None) res = lnt.lint_path(filepath, fix=True) # If we have a violations structure, let's enforce it. if violations: vs = set(res.check_tuples()) # Format the violations file expected_vs = set() for rule_key in violations["violations"]["linting"]: for elem in violations["violations"]["linting"][rule_key]: expected_vs.add((rule_key, *elem)) assert expected_vs == vs # Actually do the fixes res = do_fixes(lnt, res) # Read the fixed file with open(filepath, mode='r') as fixed_file: fixed_buff = fixed_file.read() # Clearup once read shutil.rmtree(tempdir_path) # Read the comparison file with open(cmp_filepath, mode='r') as comp_file: comp_buff = comp_file.read() # Make sure we were successful assert res # Assert that we fixed as expected assert fixed_buff == comp_buff
def initialize(self): self._app = Linter(config=FluffConfig.from_root())
def test__linter__path_from_paths__not_exist(): """Test extracting paths from a file path.""" lntr = Linter(config=FluffConfig()) with pytest.raises(IOError): lntr.paths_from_path('asflekjfhsakuefhse')
def test__linter__path_from_paths__not_exist_ignore(): """Test extracting paths from a file path.""" lntr = Linter(config=FluffConfig()) paths = lntr.paths_from_path('asflekjfhsakuefhse', ignore_non_existent_files=True) assert len(paths) == 0
def test__linter__path_from_paths__file(): lntr = Linter() paths = lntr.paths_from_path('test/fixtures/linter/indentation_errors.sql') assert normalise_paths(paths) == set(['test.fixtures.linter.indentation_errors.sql'])