ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SQLFluff Python API 使用指南:从 lint/fix/parse 到 Linter 与 FluffConfig 的进阶集成

SQLFluff Python API 使用指南:从 lint/fix/parse 到 Linter 与 FluffConfig 的进阶集成 SQLFluff Python API 使用指南从 lint/fix/parse 到 Linter 与 FluffConfig 的进阶集成【免费下载链接】sqlfluffA modular SQL linter and auto-formatter with support for multiple dialects and templated code.项目地址: https://gitcode.com/GitHub_Trending/sq/sqlfluffSQLFluff 不仅是一个 CLI 工具它还对外暴露了一套完善的 Python API供其他 Python 应用直接调用其 lint、fix、parse 核心能力。本文以 docs/source/reference/api.rst 为骨架结合仓库内 examples 目录下的官方示例与 src/sqlfluff 源码实现系统讲解简单 APIsqlfluff.lint/sqlfluff.fix/sqlfluff.parse与高级 APILinter、FluffConfig、Lexer、Parser的完整用法帮助你在自己的 Python 工程中把 SQLFluff 作为库无缝集成。为什么需要 Python APISQLFluff 的日常使用场景是命令行sqlfluff lint、sqlfluff fix可以解决大部分手工需求。但当 SQLFluff 需要成为另一个系统的一部分时——例如在 CI/CD 脚本或平台后端中对动态生成的 SQL 字符串做实时检查在编辑器/IDE 插件中解析 SQL 并高亮语法树节点在数据工程框架中批量修复不符合规范的文件在自定义规则开发或性能基准测试中直接驱动核心组件此时就需要调用 SQLFluff 的 Python API。官方在 docs/source/reference/api.rst 中明确说明SQLFluff 向其他 Python 应用暴露了一个公共 API并按简单 API与高级 API两个层次组织。从源码看这一分层体现在 src/sqlfluff/api/init.py简单 API 由sqlfluff.api.simple模块提供__all__中暴露了lint、fix、parse、APIParsingError、list_rules、list_dialects六个公开成员全部基于sqlfluff.core中的核心类实现。简单 API一行代码完成 lint / fix / parse简单 API 的三个核心方法签名位于 src/sqlfluff/api/simple.py它们都接收sql字符串并返回 Python 原生类型非常适合快速集成。官方示例 examples/01_basic_api_usage.py 给出了完整的入门代码import sqlfluff my_bad_query SeLEct *, 1, blah as fOO from mySchema.myTable # -------- LINTING ---------- lint_result sqlfluff.lint(my_bad_query, dialectbigquery) # lint_result # [ # { # code: CP01, # line_no: 1, # line_pos: 1, # description: Keywords must be consistently upper case., # } # ... # ] # -------- FIXING ---------- fix_result_1 sqlfluff.fix(my_bad_query, dialectbigquery) # fix_result_1 SELECT *, 1, blah AS foo FROM myschema.mytable\n # 只修复指定规则 fix_result_2 sqlfluff.fix(my_bad_query, rules[CP01]) # fix_result_2 SELECT *, 1, blah AS fOO FROM mySchema.myTable # 修复规则子集 fix_result_3 sqlfluff.fix(my_bad_query, rules[CP01, CP02]) # fix_result_3 SELECT *, 1, blah AS fOO FROM myschema.mytable # -------- PARSING ---------- parse_result sqlfluff.parse(my_bad_query) # parse_result {file: {statement: {...}, newline: \n}}lint()获取违规列表sqlfluff.lint(sql, dialect, rules, exclude_rules, config, config_path)返回一个list[dict]每个 dict 是一条违规记录包含规则代码如CP01、行号line_no、列号line_pos与描述description。其实现流程见 src/sqlfluff/api/simple.py是通过get_simple_config()根据参数构建FluffConfig实例化Linter(configcfg)调用linter.lint_string_wrapped(sql)得到LintingResult调用result.as_records()并取出第一个文件的violations列表返回。fix()自动修复并返回新字符串sqlfluff.fix(...)比lint多一个fix_even_unparsable: Optional[bool]参数src/sqlfluff/api/simple.py。其核心行为值得注意若 SQL 存在模板化或解析错误默认fix_even_unparsable未设置时读取配置cfg.get(fix_even_unparsable)不会执行修复而是原样返回字符串避免在无法解析的代码上盲目改动。只有满足可修复条件时才执行result.paths[0].files[0].fix_string()[0]取出修复后的文本。parse()获取语法树 JSONsqlfluff.parse(sql, dialect, config, config_path)返回解析树的 JSON 字典表示src/sqlfluff/api/simple.py。两点实现细节如果解析过程中产生任何违规violations会统一抛出APIParsingError继承自ValueError异常对象上挂有violations列表可通过 try/except 捕获后逐个查看若源文件存在多个解析变体variants简单 API 只返回第一个变体需要访问全部变体时须改用核心 API。官方示例同时展示了如何递归遍历 parse 返回的 JSON 树来提取感兴趣的信息examples/01_basic_api_usage.pydef get_json_segment(parse_result, segment_type): 递归在 parse 结果 JSON 中搜索指定 segment 类型。 for k, v in parse_result.items(): if k segment_type: yield v elif isinstance(v, dict): yield from get_json_segment(v, segment_type) elif isinstance(v, list): for s in v: yield from get_json_segment(s, segment_type) # 提取所有表引用 table_references list(get_json_segment(parse_result, table_reference)) print(table_references) # [[{identifier: mySchema}, {dot: .}, {identifier: myTable}]]这种 JSON 结构便于程序化分析 SQL 的对象引用是开发 SQL 血缘分析、对象浏览工具时的常用手法。枚举方言与规则list_dialects() / list_rules()examples/03_getting_rules_and_dialects.py 演示了如何枚举 SQLFluff 支持的能力import sqlfluff dialects sqlfluff.list_dialects() # dialects [DialectTuple(labelansi, nameansi, inherits_fromnothing), ...] dialect_names [dialect.label for dialect in dialects] # dialect_names [ansi, snowflake, ...] rules sqlfluff.list_rules() # rules [RuleTuple(codeExample_LT01, descriptionORDER BY on these columns is forbidden!), ...] rule_codes [rule.code for rule in rules] # rule_codes [LT01, LT02, ...]其实现位于 src/sqlfluff/api/info.pylist_rules()通过Linter().rule_tuples()获取规则元组list_dialects()则直接返回dialect_readout()的方言元组列表。这对构建动态规则选择器、方言下拉框等 UI 场景很有价值。简单 API 的三种配置方式简单 API 虽然参数少但配置灵活度并不低。examples/05_simple_api_config.py 明确了三种配置途径import sqlfluff from sqlfluff.core import FluffConfig # 1. 有限的 kwargs sqlfluff.fix(SELECT 1, dialectbigquery) # 2. 提供配置文件路径 sqlfluff.fix(SELECT 1, config_pathtest/fixtures/.sqlfluff) # 3. 提供预构建的 FluffConfig 对象控制力最强 sqlfluff.fix(SELECT 1, configconfig)其中config_path与config的关系从lint/fix/parse的源码可见一斑cfg config or get_simple_config(...)即只有未传入config对象时config_path才会被使用src/sqlfluff/api/simple.py。而get_simple_config()内部src/sqlfluff/api/simple.py还会做几件值得注意的事校验dialect是否存在通过dialect_selector(dialect)查找找不到时抛出SQLFluffUserError: Error: Unknown dialect ...将rules/exclude_rules列表以逗号拼接写入overrides调用FluffConfig.from_root(extra_config_pathconfig_path, ignore_local_configTrue, overridesoverrides, require_dialectFalse)其中ignore_local_configTrue意味着简单 API默认忽略用户主目录与 appdir 下的配置文件只认config_path与传入参数行为可预期若最终仍未设置方言则回退到ansi保持简单 API 的历史兼容行为。高级 APILinter 与 FluffConfig官方文档指出简单 API 只是sqlfluff.core核心库功能的冰山一角。更复杂的场景应直接使用Linter()与FluffConfig()类。需要注意从 0.4.0 版本起核心 API 仍标记为实验性内部结构可能在后续版本无预警变化如果你开始依赖 SQLFluff 内部 API官方建议在 GitHub 提交 issue 反馈你的使用场景以帮助塑造更稳定、整洁、文档完善的公共 API。用 FluffConfig 配置 SQLFluff 行为FluffConfig是所有配置的载体可以手动构造也可以从各种来源解析。examples/05_simple_api_config.py 演示了 5 种构造方式from sqlfluff.core import FluffConfig # 3a. 直接从字典创建 config FluffConfig(configs{core: {dialect: bigquery}}) # 3b. 从单个配置字符串创建INI 格式类似 .sqlfluff 文件 config FluffConfig.from_string([sqlfluff]\ndialectbigquery\n) # 3c. 从多个配置字符串创建模拟嵌套配置文件的叠加效果 config FluffConfig.from_strings( # 注意给定这两个字符串最终方言是 mysql因为后者优先 [sqlfluff]\ndialectbigquery\n, [sqlfluff]\ndialectmysql\n, ) # 3d. 从包含配置文件的路径创建 config FluffConfig.from_path(test/fixtures/) # 3e. 从关键字参数创建 config FluffConfig.from_kwargs(dialectbigquery, rules[LT01]) # 之后通过 config 参数传入 sqlfluff.fix(SELECT 1, configconfig)各工厂方法的语义在 src/sqlfluff/core/config/fluffconfig.py 中有明确定义from_strings(*config_strings)L347-L377按传入顺序从第一个到最后一个依次合并靠后的配置字符串优先级更高用于模拟嵌套配置文件的叠加效果from_path(path)L380-L431从工作目录到目标路径之间找到的所有配置文件都会被加载越靠近目标路径的文件优先级越高from_root()L279-L318基于当前根目录向上搜索配置支持extra_config_path、ignore_local_config、overrides、require_dialect等参数是简单 API 内部使用的入口from_kwargs(dialect, rules, exclude_rules)L434-L459为Linter()、Parser()、Lexer()这类公共类直接设置常用属性而提供的便捷方法规则说明符可以是代码、名称、分组或别名。overrides参数在所有工厂方法中语义一致作为最后合并的配置优先级高于其他一切来源并会被子配置继承——这正是 CLI 把命令行参数应用到所有被 lint 文件的方式src/sqlfluff/core/config/fluffconfig.py。用 overrides 覆盖配置文件Linter FluffConfig 完整示例examples/04_config_overrides.py 展示了将两者结合的标准姿势from sqlfluff.core import FluffConfig, Linter sql SELECT 1\n config FluffConfig( overrides{ dialect: snowflake, # NOTE: 这里显式设置字符串 none 而不是 None 字面量 # 以便覆盖路径中任何配置文件已设置的 library_path。 library_path: none, } ) linted_file Linter(configconfig).lint_string(sql) assert linted_file.get_violations() []这个示例蕴含两个实战要点Linter(configconfig)在实例化时绑定配置之后该实例的所有操作都使用这份配置要覆盖路径下配置文件已有的设置必须使用字符串none而非 Python 的None字面量——None会被视为未提供从而无法覆盖配置文件中的值。这是使用 overrides 时最容易踩的坑。Linter.lint_string(sql, fixTrue)返回LintedFile对象src/sqlfluff/core/linter/linter.py内部流程为parse_string()解析 →get_rulepack()获取规则包 →lint_parsed()执行规则。随后可调用linted_file.get_violations()获取违规或如示例所示用lint_result.fix_string()取出修复结果linter Linter(configconfig) lint_result linter.lint_string(SELECT 1, fixTrue) fixed_string lint_result.fix_string() # NOTE: True 表示修复成功 assert fixed_string (SELECT 1, True)lint_string的关键签名参数包括in_str、fname文件名默认string input可用于错误报告定位、fix: bool、config局部覆盖配置与encoding默认utf8。核心管道Lexer → Parser → Linter文档的高级 API 参考部分还导出了Lexer与Parser见 src/sqlfluff/core/init.py 的__all__。仓库提供的性能示例 examples/02_timing_api_steps.py 正好展示了这三者的流水线关系与逐级调用方式import timeit from sqlfluff.core import Lexer, Linter, Parser sql SeLEct *, 1, blah as fOO from myTable kwargs dict(dialectansi) lexer Lexer(**kwargs) parser Parser(**kwargs) linter Linter(**kwargs) # 预处理lex → parse tokens, _ lexer.lex(sql) parsed parser.parse(tokens) # 分步计时 time_function(lambda: lexer.lex(sql), namelex) time_function(lambda: parser.parse(tokens), nameparse) time_function(lambda: linter.lint(parsed), namelint) time_function(lambda: linter.fix(parsed), namefix)这里体现了核心 API 的一个显著特点Lexer、Parser、Linter都支持通过from_kwargs风格的关键字参数直接指定 dialect而非必须构造完整FluffConfig且linter.lint(tree)/linter.fix(tree)直接接收已解析的语法树BaseSegment而不是原始字符串——这与简单 API 的字符串输入形成对比。若需要细粒度控制解析与规则执行之间的环节、或对同一棵树反复执行不同规则集这种分步调用方式更为合适。从实现上看Linter.lint(tree)与Linter.fix(tree)都经由lint_fix_parsed()完成src/sqlfluff/core/linter/linter.py区别仅在于fixTrue/False与返回值的取舍fix返回(fixed_tree, violations)lint仅返回violations。Parser与Lexer则分别对应词法分析与语法分析两个阶段共同构成 SQLFluff 的解析管道。简单 API 与核心 API 的选择建议综合官方文档与源码实现可以给出如下选型参考场景推荐 API依据快速校验/修复一段 SQL 字符串简单 APIsqlfluff.lint/fix/parse开箱即用返回原生 Python 类型自动处理配置需要多个解析变体核心 APILinter.parse_string()简单 API 只返回第一个变体src/sqlfluff/api/simple.py精细控制配置叠加、覆盖路径配置FluffConfigLinteroverrides、from_strings等多来源合并能力分阶段性能分析/复用语法树Lexer→Parser→Linter见 examples/02_timing_api_steps.py批量处理文件目录、多进程核心 APILinter.lint_paths()简单 API 仅面向字符串需要留意两点限制其一核心 API 自 0.4.0 起仍标记为实验性内部接口可能在未来版本变动其二简单 API 的parse()在存在解析错误时会直接抛出APIParsingError业务代码中务必做好异常捕获。若你的项目需要稳定的程序化 SQL 检查能力可将简单 API 封装为服务层把FluffConfig的构建集中管理同时隔离核心 API 的实验性变化。进一步阅读官方 API 参考docs/source/reference/api.rst五个官方示例examples 目录基础用法、计时、方言/规则枚举、配置覆盖、多种配置方式简单 API 实现src/sqlfluff/api/simple.py 与 src/sqlfluff/api/info.py配置对象实现src/sqlfluff/core/config/fluffconfig.py核心类实现src/sqlfluff/core/linter/linter.py 与 src/sqlfluff/core/init.py配置项全览docs/source/configuration/default_configuration.rst简单 API 测试用例test/api/simple_test.py 与 test/api/info_test.py【免费下载链接】sqlfluffA modular SQL linter and auto-formatter with support for multiple dialects and templated code.项目地址: https://gitcode.com/GitHub_Trending/sq/sqlfluff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表