sqlty 0.0.1.dev1__tar.gz → 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. sqlty-0.1.0/PKG-INFO +210 -0
  2. sqlty-0.1.0/README.md +176 -0
  3. sqlty-0.1.0/pyproject.toml +171 -0
  4. sqlty-0.1.0/rust/Cargo.lock +876 -0
  5. sqlty-0.1.0/rust/Cargo.toml +58 -0
  6. sqlty-0.1.0/rust/crates/sqlty-ext/Cargo.toml +22 -0
  7. sqlty-0.1.0/rust/crates/sqlty-ext/src/lib.rs +937 -0
  8. sqlty-0.1.0/rust/crates/sqlty-python/Cargo.toml +17 -0
  9. sqlty-0.1.0/rust/crates/sqlty-python/src/checker.rs +1442 -0
  10. sqlty-0.1.0/rust/crates/sqlty-python/src/edit.rs +54 -0
  11. sqlty-0.1.0/rust/crates/sqlty-python/src/fixer.rs +239 -0
  12. sqlty-0.1.0/rust/crates/sqlty-python/src/lib.rs +41 -0
  13. sqlty-0.1.0/rust/crates/sqlty-python/src/options.rs +50 -0
  14. sqlty-0.1.0/rust/crates/sqlty-python/src/rewriter.rs +1528 -0
  15. sqlty-0.1.0/rust/crates/sqlty-python/src/rules.rs +351 -0
  16. sqlty-0.1.0/rust/crates/sqlty-python/src/scan.rs +201 -0
  17. sqlty-0.1.0/rust/crates/sqlty-python/src/template.rs +212 -0
  18. sqlty-0.1.0/rust/crates/sqlty-python/src/tokens.rs +708 -0
  19. sqlty-0.1.0/rust/crates/sqlty-sql/Cargo.toml +28 -0
  20. sqlty-0.1.0/rust/crates/sqlty-sql/build.rs +45 -0
  21. sqlty-0.1.0/rust/crates/sqlty-sql/rules/README.md +185 -0
  22. sqlty-0.1.0/rust/crates/sqlty-sql/rules/common/aggregates.inference.toml +61 -0
  23. sqlty-0.1.0/rust/crates/sqlty-sql/rules/common/arithmetic.inference.toml +54 -0
  24. sqlty-0.1.0/rust/crates/sqlty-sql/rules/common/comparison.inference.toml +60 -0
  25. sqlty-0.1.0/rust/crates/sqlty-sql/rules/common/concat.inference.toml +35 -0
  26. sqlty-0.1.0/rust/crates/sqlty-sql/rules/common/json.inference.toml +46 -0
  27. sqlty-0.1.0/rust/crates/sqlty-sql/rules/compile.rs +737 -0
  28. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/aggregates.inference.toml +21 -0
  29. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/arithmetic.inference.toml +30 -0
  30. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/comparison.inference.toml +10 -0
  31. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/concat.inference.toml +9 -0
  32. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/json.inference.toml +21 -0
  33. sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/strings.inference.toml +51 -0
  34. sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/aggregates.inference.toml +51 -0
  35. sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/arithmetic.inference.toml +342 -0
  36. sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/concat.inference.toml +49 -0
  37. sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/json.inference.toml +123 -0
  38. sqlty-0.1.0/rust/crates/sqlty-sql/rules/sqlite/json.inference.toml +28 -0
  39. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/api.rs +187 -0
  40. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/dialect.rs +171 -0
  41. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/dialect_functions.rs +379 -0
  42. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/dml.rs +388 -0
  43. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/explain.rs +126 -0
  44. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/expr.rs +704 -0
  45. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/functions.rs +921 -0
  46. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/grouping.rs +244 -0
  47. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/hashing.rs +30 -0
  48. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/inference.rs +320 -0
  49. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/json.rs +738 -0
  50. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/literals.rs +248 -0
  51. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/memo.rs +125 -0
  52. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/mod.rs +115 -0
  53. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/names.rs +347 -0
  54. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/narrowing.rs +686 -0
  55. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/nullability.rs +1188 -0
  56. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/operators.rs +567 -0
  57. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/params.rs +1054 -0
  58. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/preprocess.rs +388 -0
  59. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/query.rs +968 -0
  60. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/references.rs +82 -0
  61. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/registry.rs +439 -0
  62. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/resolve.rs +749 -0
  63. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/scope.rs +948 -0
  64. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__dml__tests__returning_columns_in_queries.snap +48 -0
  65. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__arrays_and_subscripts.snap +36 -0
  66. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__case_expressions.snap +28 -0
  67. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__casts.snap +41 -0
  68. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__casts_without_a_schema_do_not_complain.snap +9 -0
  69. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__composite_fields_and_json_access.snap +24 -0
  70. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__literals_and_unary_operators.snap +29 -0
  71. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__misc_expressions.snap +38 -0
  72. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__mysql_and_sqlite_expressions.snap +31 -0
  73. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__aggregates_in_postgres.snap +44 -0
  74. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__function_availability_differs_by_dialect.snap +37 -0
  75. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__return_types_follow_the_argument.snap +74 -0
  76. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__unknown_functions_are_untyped_and_explained.snap +16 -0
  77. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__literals__tests__value_sets_flow_through_expressions.snap +43 -0
  78. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__names__tests__column_names_follow_postgres_figure_colname.snap +34 -0
  79. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__arithmetic_promotes_numbers_and_types_date_math.snap +149 -0
  80. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__binary_operators_in_queries.snap +58 -0
  81. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__common_type_follows_postgres_union_rules.snap +24 -0
  82. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__division_differs_between_postgres_and_mysql.snap +14 -0
  83. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__column_names_come_from_the_first_branch.snap +9 -0
  84. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__ctes.snap +18 -0
  85. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__dialects_name_and_type_the_same_query_differently.snap +33 -0
  86. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__projection_forms.snap +42 -0
  87. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__recursive_ctes_settle_nullability.snap +17 -0
  88. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__set_operations_combine_nullability.snap +27 -0
  89. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__set_operations_unify_types.snap +30 -0
  90. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__statements_that_are_not_queries_have_no_columns.snap +21 -0
  91. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__unsupported_query_forms_are_explained.snap +13 -0
  92. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__values_lists.snap +32 -0
  93. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__ambiguous_names_are_reported_once_per_query.snap +30 -0
  94. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__cte_columns_are_resolved_like_tables.snap +18 -0
  95. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__names_are_not_judged_without_a_schema.snap +15 -0
  96. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__nullability_comes_from_the_declaration.snap +15 -0
  97. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__quoted_names_keep_their_case_in_postgres_only.snap +29 -0
  98. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__star_over_unreadable_sources_names_the_reason.snap +31 -0
  99. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__system_columns_exist_without_being_declared.snap +29 -0
  100. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__unknown_names_say_what_is_missing.snap +47 -0
  101. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__unqualified_names_resolve_to_the_first_source_that_has_them.snap +24 -0
  102. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__correlated_subqueries_see_the_outer_scope.snap +21 -0
  103. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__derived_tables_ctes_and_views.snap +36 -0
  104. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__nullability_follows_the_join_kind.snap +33 -0
  105. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__opaque_sources_explain_themselves.snap +51 -0
  106. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__star_expansion_over_joins.snap +49 -0
  107. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__table_names_fold_by_dialect.snap +28 -0
  108. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/sql_type.rs +926 -0
  109. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/star_expand.rs +257 -0
  110. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/table_functions.rs +237 -0
  111. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/test_support.rs +62 -0
  112. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/tests.rs +421 -0
  113. sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/typed.rs +111 -0
  114. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/alter.rs +345 -0
  115. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/builtin_catalog.sql +190 -0
  116. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/columns.rs +347 -0
  117. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/loader.rs +766 -0
  118. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/mod.rs +910 -0
  119. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/names.rs +165 -0
  120. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/read.rs +236 -0
  121. sqlty-0.1.0/rust/crates/sqlty-sql/src/catalog/resolve.rs +467 -0
  122. sqlty-0.1.0/rust/crates/sqlty-sql/src/ddl.rs +845 -0
  123. sqlty-0.1.0/rust/crates/sqlty-sql/src/diagnostics.rs +269 -0
  124. sqlty-0.1.0/rust/crates/sqlty-sql/src/json.rs +486 -0
  125. sqlty-0.1.0/rust/crates/sqlty-sql/src/lib.rs +40 -0
  126. sqlty-0.1.0/rust/crates/sqlty-sql/src/placeholders.rs +324 -0
  127. sqlty-0.1.0/rust/crates/sqlty-sql/src/values.rs +344 -0
  128. sqlty-0.1.0/rust/crates/sqlty-sql/tests/inference_compiler.rs +282 -0
  129. sqlty-0.1.0/rust/crates/sqlty-sql/tests/timing.rs +70 -0
  130. sqlty-0.1.0/src/sqlty/__init__.py +99 -0
  131. {sqlty-0.0.1.dev1 → sqlty-0.1.0}/src/sqlty/__main__.py +1 -1
  132. sqlty-0.1.0/src/sqlty/_breaking.py +191 -0
  133. sqlty-0.1.0/src/sqlty/_check.py +880 -0
  134. sqlty-0.1.0/src/sqlty/_cli.py +1219 -0
  135. sqlty-0.1.0/src/sqlty/_config.py +666 -0
  136. sqlty-0.1.0/src/sqlty/_core.pyi +108 -0
  137. sqlty-0.1.0/src/sqlty/_decode.py +62 -0
  138. sqlty-0.1.0/src/sqlty/_drivers.py +274 -0
  139. sqlty-0.1.0/src/sqlty/_gitignore.py +58 -0
  140. sqlty-0.1.0/src/sqlty/_helpers.py +613 -0
  141. sqlty-0.1.0/src/sqlty/_json_shape.py +299 -0
  142. sqlty-0.1.0/src/sqlty/_json_types.py +225 -0
  143. sqlty-0.1.0/src/sqlty/_lint.py +350 -0
  144. sqlty-0.1.0/src/sqlty/_params.py +177 -0
  145. sqlty-0.1.0/src/sqlty/_psycopg.py +269 -0
  146. sqlty-0.1.0/src/sqlty/_source.py +654 -0
  147. sqlty-0.1.0/src/sqlty/_type_extractor/__init__.py +51 -0
  148. sqlty-0.1.0/src/sqlty/_type_extractor/ast_fields.py +823 -0
  149. sqlty-0.1.0/src/sqlty/_type_extractor/compat.py +252 -0
  150. sqlty-0.1.0/src/sqlty/_type_extractor/extract.py +179 -0
  151. sqlty-0.1.0/src/sqlty/_type_extractor/generic.py +95 -0
  152. sqlty-0.1.0/src/sqlty/_type_extractor/info.py +161 -0
  153. sqlty-0.1.0/src/sqlty/_type_extractor/sandbox.py +385 -0
  154. sqlty-0.1.0/src/sqlty/_type_extractor/subtype.py +156 -0
  155. sqlty-0.1.0/src/sqlty/_widening.py +89 -0
  156. sqlty-0.1.0/src/sqlty/core.py +566 -0
  157. sqlty-0.1.0/src/sqlty/drivers/psycopg.py +104 -0
  158. sqlty-0.1.0/src/sqlty/magic.py +126 -0
  159. sqlty-0.1.0/src/sqlty/rules/ambiguous-column.md +48 -0
  160. sqlty-0.1.0/src/sqlty/rules/column-count-mismatch.md +30 -0
  161. sqlty-0.1.0/src/sqlty/rules/column-name-mismatch.md +34 -0
  162. sqlty-0.1.0/src/sqlty/rules/column-type-mismatch.md +75 -0
  163. sqlty-0.1.0/src/sqlty/rules/fstring-skipped.md +23 -0
  164. sqlty-0.1.0/src/sqlty/rules/inline-sql-comment.md +27 -0
  165. sqlty-0.1.0/src/sqlty/rules/insert-missing-column.md +58 -0
  166. sqlty-0.1.0/src/sqlty/rules/json-shape-mismatch.md +96 -0
  167. sqlty-0.1.0/src/sqlty/rules/literal-mismatch.md +83 -0
  168. sqlty-0.1.0/src/sqlty/rules/mysql-sql-marker.md +32 -0
  169. sqlty-0.1.0/src/sqlty/rules/nullable-mismatch.md +76 -0
  170. sqlty-0.1.0/src/sqlty/rules/param-count-mismatch.md +66 -0
  171. sqlty-0.1.0/src/sqlty/rules/param-type-mismatch.md +73 -0
  172. sqlty-0.1.0/src/sqlty/rules/redundant-literal.md +68 -0
  173. sqlty-0.1.0/src/sqlty/rules/redundant-optional.md +100 -0
  174. sqlty-0.1.0/src/sqlty/rules/select-star-no-schema.md +24 -0
  175. sqlty-0.1.0/src/sqlty/rules/select-star.md +77 -0
  176. sqlty-0.1.0/src/sqlty/rules/stale-rewrite.md +33 -0
  177. sqlty-0.1.0/src/sqlty/rules/stale-type.md +50 -0
  178. sqlty-0.1.0/src/sqlty/rules/tstring-skipped.md +68 -0
  179. sqlty-0.1.0/src/sqlty/rules/typeddict-inheritance.md +35 -0
  180. sqlty-0.1.0/src/sqlty/rules/typeddict-key-mismatch.md +38 -0
  181. sqlty-0.1.0/src/sqlty/rules/unchecked-query.md +34 -0
  182. sqlty-0.1.0/src/sqlty/rules/ungrouped-column.md +67 -0
  183. sqlty-0.1.0/src/sqlty/rules/unknown-column.md +68 -0
  184. sqlty-0.1.0/src/sqlty/rules/unknown-function.md +49 -0
  185. sqlty-0.1.0/src/sqlty/rules/unknown-table.md +47 -0
  186. sqlty-0.1.0/src/sqlty/rules/unknown-type.md +74 -0
  187. sqlty-0.1.0/src/sqlty/rules/unparsed-query.md +46 -0
  188. sqlty-0.1.0/src/sqlty/rules/unsupported-syntax.md +69 -0
  189. sqlty-0.1.0/src/sqlty/rules/untyped-query.md +39 -0
  190. sqlty-0.1.0/src/sqlty/rules/unused-ignore.md +36 -0
  191. sqlty-0.1.0/src/sqlty/skill/SKILL.md +110 -0
  192. sqlty-0.1.0/src/sqlty_magic.pth +1 -0
  193. sqlty-0.0.1.dev1/.gitignore +0 -20
  194. sqlty-0.0.1.dev1/PKG-INFO +0 -187
  195. sqlty-0.0.1.dev1/README.md +0 -138
  196. sqlty-0.0.1.dev1/pyproject.toml +0 -139
  197. sqlty-0.0.1.dev1/src/sqlty/__init__.py +0 -55
  198. sqlty-0.0.1.dev1/src/sqlty/_ast_builder.py +0 -211
  199. sqlty-0.0.1.dev1/src/sqlty/_ast_unparser.py +0 -215
  200. sqlty-0.0.1.dev1/src/sqlty/_auto_generator.py +0 -44
  201. sqlty-0.0.1.dev1/src/sqlty/_collector.py +0 -126
  202. sqlty-0.0.1.dev1/src/sqlty/_config.py +0 -114
  203. sqlty-0.0.1.dev1/src/sqlty/_generator.py +0 -587
  204. sqlty-0.0.1.dev1/src/sqlty/_registry.py +0 -146
  205. sqlty-0.0.1.dev1/src/sqlty/_sql_analyzer.py +0 -228
  206. sqlty-0.0.1.dev1/src/sqlty/_stub_merger.py +0 -275
  207. sqlty-0.0.1.dev1/src/sqlty/drivers/psycopg.py +0 -12
  208. {sqlty-0.0.1.dev1 → sqlty-0.1.0}/LICENSE +0 -0
  209. {sqlty-0.0.1.dev1 → sqlty-0.1.0}/src/sqlty/py.typed +0 -0
sqlty-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlty
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Environment :: Console
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Programming Language :: Python :: 3.14
10
+ Classifier: Programming Language :: Python :: 3.15
11
+ Classifier: Programming Language :: Rust
12
+ Classifier: Programming Language :: SQL
13
+ Classifier: Topic :: Software Development :: Code Generators
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: Database
16
+ Classifier: Typing :: Typed
17
+ Requires-Dist: pathspec>=0.12.1
18
+ Requires-Dist: typing-extensions>=4.15.0 ; python_full_version < '3.15'
19
+ Requires-Dist: psycopg>=3.2.12 ; extra == 'psycopg'
20
+ Provides-Extra: psycopg
21
+ License-File: LICENSE
22
+ Summary: Type-safe SQL queries for Python
23
+ Keywords: sql,type-hints,mypy,type-safety,static-analysis,code-generation
24
+ Author-email: Jiri Kuncar <jiri.kuncar@gmail.com>
25
+ License-Expression: MIT
26
+ Requires-Python: >=3.14
27
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
28
+ Project-URL: Changelog, https://github.com/jirikuncar/sqlty/releases
29
+ Project-URL: Documentation, https://jirikuncar.github.io/sqlty/
30
+ Project-URL: Homepage, https://github.com/jirikuncar/sqlty
31
+ Project-URL: Issues, https://github.com/jirikuncar/sqlty/issues
32
+ Project-URL: Repository, https://github.com/jirikuncar/sqlty
33
+
34
+ # SQLTy
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/sqlty.svg)](https://pypi.org/project/sqlty/)
37
+ [![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/downloads/)
38
+ [![Tests](https://github.com/jirikuncar/sqlty/actions/workflows/tests.yml/badge.svg)](https://github.com/jirikuncar/sqlty/actions/workflows/tests.yml)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
+
41
+ Your SQL already knows its types. SQLTy tells Python.
42
+
43
+ Type-safe raw SQL without an ORM or a database connection. sqlty reads row and
44
+ parameter types from your SQL and schema, and checks them on every commit, so a
45
+ migration that changes a column is caught in review, not in production.
46
+
47
+ <p align="center">
48
+ <img src="https://raw.githubusercontent.com/jirikuncar/sqlty/main/docs/assets/demo.gif" alt="A terminal session: sqlty rewrite adds the row type to a query, a migration makes email nullable, sqlty check --fix updates the type and mypy reports the line that would crash" width="720">
49
+ <br>
50
+ <em>A migration makes <code>email</code> nullable. sqlty and mypy find the code that would crash.</em>
51
+ (<a href="https://github.com/jirikuncar/sqlty/blob/main/docs/assets/demo.tape">view source</a>)
52
+ </p>
53
+
54
+ **Documentation: [jirikuncar.github.io/sqlty](https://jirikuncar.github.io/sqlty/)**
55
+
56
+ **Fits if** you write SQL as string literals on Python 3.14+, against
57
+ PostgreSQL, SQLite or MySQL, with a schema dump or SQL migrations in the
58
+ repository. Rows are typed end to end with psycopg 3; with other drivers sqlty
59
+ checks the query and its parameters, and you annotate what the cursor returns
60
+ ([Drivers](https://jirikuncar.github.io/sqlty/guide/drivers-and-orms/)).
61
+
62
+ > **Beta.** APIs and configuration may change before 1.0. Feedback welcome in
63
+ > [GitHub Issues](https://github.com/jirikuncar/sqlty/issues).
64
+
65
+ ## How it works
66
+
67
+ Drivers return rows of `Any`, so nothing ties a query's columns to the code
68
+ that reads them. Start a query with `--sql` and a newline, and
69
+ `sqlty rewrite .` adds the row type inferred from your `CREATE TABLE`
70
+ statements:
71
+
72
+ ```toml
73
+ # pyproject.toml
74
+ [tool.sqlty]
75
+ schema = "schema.sql"
76
+ ```
77
+
78
+ `schema.sql`:
79
+
80
+ ```sql
81
+ CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email VARCHAR(255) NOT NULL);
82
+ ```
83
+
84
+ ```python
85
+ query = "--sql\nSELECT id, name, email FROM users"
86
+ # rewritten: query = SQL[tuple[int, str, str]]("--sql\nSELECT id, name, email FROM users")
87
+ ```
88
+
89
+ `SQL[T]` is a `str` subclass, so the query still runs anywhere a string does,
90
+ and mypy, pyright and ty see `T`. Without a schema, casts such as `id::INTEGER`
91
+ type the columns; a query with neither stays as it is. With a space instead of
92
+ the newline, `"--sql SELECT ..."` is a SQL comment, and `sqlty check` warns.
93
+
94
+ ## What it catches
95
+
96
+ ### A migration changes a column
97
+
98
+ ```toml
99
+ [tool.sqlty]
100
+ schema = "schema.sql"
101
+ ```
102
+
103
+ A migration dropped `NOT NULL` from `email`.
104
+
105
+ `schema.sql`:
106
+
107
+ ```sql
108
+ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
109
+ ```
110
+
111
+ ```python
112
+ from sqlty import SQL
113
+
114
+ # error: [stale-type] "SQL[tuple[int, str]] should be SQL[tuple[int, str | None]]"
115
+ query = SQL[tuple[int, str]]("--sql\nSELECT id, email FROM users")
116
+ ```
117
+
118
+ `sqlty check --fix .` updates the type, and your type checker finds every
119
+ caller that now needs a `None` check. `stale-type` is a warning by default; set
120
+ `stale-type = "error"` under `[tool.sqlty.rules]` to fail CI on it
121
+ ([CI](https://jirikuncar.github.io/sqlty/recipes/ci/)). For rolling deploys,
122
+ `sqlty breaking --against origin/main` exits 1 when old code breaks on the new
123
+ schema or new code on the old one
124
+ ([Breaking schema changes](https://jirikuncar.github.io/sqlty/guide/breaking-changes/)).
125
+
126
+ ### A row type that doesn't match its query
127
+
128
+ ```python
129
+ from typing import TypedDict
130
+ from sqlty import SQL
131
+
132
+ class User(TypedDict):
133
+ id: str
134
+ name: str
135
+
136
+ # error: [column-type-mismatch] "User.id is str but query column 'id' infers int"
137
+ query = SQL[User]("--sql\nSELECT id::INTEGER, name::TEXT FROM users")
138
+ ```
139
+
140
+ `TypedDict`, `NamedTuple`, dataclasses and Pydantic models are all checked
141
+ ([Row types](https://jirikuncar.github.io/sqlty/guide/row-types/)).
142
+
143
+ ### Wrong parameters, misspelled columns
144
+
145
+ ```toml
146
+ [tool.sqlty]
147
+ dialect = "sqlite"
148
+ schema = "schema.sql"
149
+
150
+ [tool.sqlty.rules]
151
+ unknown-column = "warn"
152
+ ```
153
+
154
+ `schema.sql`:
155
+
156
+ ```sql
157
+ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
158
+ ```
159
+
160
+ ```python
161
+ import sqlite3
162
+ from sqlty import SQL
163
+
164
+ conn = sqlite3.connect("app.db")
165
+
166
+ # error: [param-count-mismatch] "query has 1 parameter, the call passes 2"
167
+ conn.execute(SQL[tuple[str | None]]("--sql\nSELECT email FROM users WHERE id = ?"), (1, 2))
168
+
169
+ # error: [unknown-column] "column `emial` does not exist in `users`"
170
+ conn.execute("--sql\nSELECT emial FROM users")
171
+ ```
172
+
173
+ `?`, `$1`, `%s` and `:name` placeholders are checked on sqlite3, psycopg and
174
+ asyncpg calls ([Parameters](https://jirikuncar.github.io/sqlty/guide/parameters/)).
175
+ These are the mistakes coding agents make: every problem is one
176
+ `file:line: [rule] message` line and a non-zero exit code they can act on, and
177
+ the [sqlty skill](https://jirikuncar.github.io/sqlty/recipes/agents/) teaches
178
+ them the conventions.
179
+
180
+ ## Get started
181
+
182
+ ```bash
183
+ pip install "sqlty[psycopg]" # or: uv add sqlty; the extra adds the psycopg helpers
184
+ printf '%s\n' 'q = "--sql\nSELECT id::INTEGER, name::TEXT FROM users"' > queries.py
185
+ sqlty rewrite -v . # q = SQL[tuple[int, str]]("--sql\n...")
186
+ sqlty check . # report drift and mismatches
187
+ sqlty strip . # undo: back to plain strings
188
+ ```
189
+
190
+ `rewrite` and `strip` only touch the wrapper, never the SQL, so you can adopt
191
+ sqlty one module at a time and back out. New project:
192
+ [Quickstart](https://jirikuncar.github.io/sqlty/quickstart/). Existing codebase:
193
+ [Migration](https://jirikuncar.github.io/sqlty/recipes/migration/), starting
194
+ with `pg_dump --schema-only app > schema.sql`.
195
+
196
+ Not a fit for ORMs, SQL built at runtime, or runtime validation;
197
+ [Why SQLTy?](https://jirikuncar.github.io/sqlty/motivation/) compares it with
198
+ sqlc, sqlx, PgTyped and others.
199
+
200
+ ## About
201
+
202
+ The engine is Rust ([sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs)
203
+ via [PyO3](https://pyo3.rs)), with wheels for Linux, macOS and Windows. SQLTy is
204
+ developed with AI coding agents, mainly Claude Code; every change is reviewed by
205
+ a maintainer (see the
206
+ [AI-assisted contributions](https://github.com/jirikuncar/sqlty/blob/main/CONTRIBUTING.md#ai-assisted-contributions)
207
+ policy). [Contributing](https://github.com/jirikuncar/sqlty/blob/main/CONTRIBUTING.md) ·
208
+ [Credits](https://jirikuncar.github.io/sqlty/credits/) ·
209
+ MIT [License](https://github.com/jirikuncar/sqlty/blob/main/LICENSE).
210
+
sqlty-0.1.0/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # SQLTy
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/sqlty.svg)](https://pypi.org/project/sqlty/)
4
+ [![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/downloads/)
5
+ [![Tests](https://github.com/jirikuncar/sqlty/actions/workflows/tests.yml/badge.svg)](https://github.com/jirikuncar/sqlty/actions/workflows/tests.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ Your SQL already knows its types. SQLTy tells Python.
9
+
10
+ Type-safe raw SQL without an ORM or a database connection. sqlty reads row and
11
+ parameter types from your SQL and schema, and checks them on every commit, so a
12
+ migration that changes a column is caught in review, not in production.
13
+
14
+ <p align="center">
15
+ <img src="https://raw.githubusercontent.com/jirikuncar/sqlty/main/docs/assets/demo.gif" alt="A terminal session: sqlty rewrite adds the row type to a query, a migration makes email nullable, sqlty check --fix updates the type and mypy reports the line that would crash" width="720">
16
+ <br>
17
+ <em>A migration makes <code>email</code> nullable. sqlty and mypy find the code that would crash.</em>
18
+ (<a href="https://github.com/jirikuncar/sqlty/blob/main/docs/assets/demo.tape">view source</a>)
19
+ </p>
20
+
21
+ **Documentation: [jirikuncar.github.io/sqlty](https://jirikuncar.github.io/sqlty/)**
22
+
23
+ **Fits if** you write SQL as string literals on Python 3.14+, against
24
+ PostgreSQL, SQLite or MySQL, with a schema dump or SQL migrations in the
25
+ repository. Rows are typed end to end with psycopg 3; with other drivers sqlty
26
+ checks the query and its parameters, and you annotate what the cursor returns
27
+ ([Drivers](https://jirikuncar.github.io/sqlty/guide/drivers-and-orms/)).
28
+
29
+ > **Beta.** APIs and configuration may change before 1.0. Feedback welcome in
30
+ > [GitHub Issues](https://github.com/jirikuncar/sqlty/issues).
31
+
32
+ ## How it works
33
+
34
+ Drivers return rows of `Any`, so nothing ties a query's columns to the code
35
+ that reads them. Start a query with `--sql` and a newline, and
36
+ `sqlty rewrite .` adds the row type inferred from your `CREATE TABLE`
37
+ statements:
38
+
39
+ ```toml
40
+ # pyproject.toml
41
+ [tool.sqlty]
42
+ schema = "schema.sql"
43
+ ```
44
+
45
+ `schema.sql`:
46
+
47
+ ```sql
48
+ CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email VARCHAR(255) NOT NULL);
49
+ ```
50
+
51
+ ```python
52
+ query = "--sql\nSELECT id, name, email FROM users"
53
+ # rewritten: query = SQL[tuple[int, str, str]]("--sql\nSELECT id, name, email FROM users")
54
+ ```
55
+
56
+ `SQL[T]` is a `str` subclass, so the query still runs anywhere a string does,
57
+ and mypy, pyright and ty see `T`. Without a schema, casts such as `id::INTEGER`
58
+ type the columns; a query with neither stays as it is. With a space instead of
59
+ the newline, `"--sql SELECT ..."` is a SQL comment, and `sqlty check` warns.
60
+
61
+ ## What it catches
62
+
63
+ ### A migration changes a column
64
+
65
+ ```toml
66
+ [tool.sqlty]
67
+ schema = "schema.sql"
68
+ ```
69
+
70
+ A migration dropped `NOT NULL` from `email`.
71
+
72
+ `schema.sql`:
73
+
74
+ ```sql
75
+ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
76
+ ```
77
+
78
+ ```python
79
+ from sqlty import SQL
80
+
81
+ # error: [stale-type] "SQL[tuple[int, str]] should be SQL[tuple[int, str | None]]"
82
+ query = SQL[tuple[int, str]]("--sql\nSELECT id, email FROM users")
83
+ ```
84
+
85
+ `sqlty check --fix .` updates the type, and your type checker finds every
86
+ caller that now needs a `None` check. `stale-type` is a warning by default; set
87
+ `stale-type = "error"` under `[tool.sqlty.rules]` to fail CI on it
88
+ ([CI](https://jirikuncar.github.io/sqlty/recipes/ci/)). For rolling deploys,
89
+ `sqlty breaking --against origin/main` exits 1 when old code breaks on the new
90
+ schema or new code on the old one
91
+ ([Breaking schema changes](https://jirikuncar.github.io/sqlty/guide/breaking-changes/)).
92
+
93
+ ### A row type that doesn't match its query
94
+
95
+ ```python
96
+ from typing import TypedDict
97
+ from sqlty import SQL
98
+
99
+ class User(TypedDict):
100
+ id: str
101
+ name: str
102
+
103
+ # error: [column-type-mismatch] "User.id is str but query column 'id' infers int"
104
+ query = SQL[User]("--sql\nSELECT id::INTEGER, name::TEXT FROM users")
105
+ ```
106
+
107
+ `TypedDict`, `NamedTuple`, dataclasses and Pydantic models are all checked
108
+ ([Row types](https://jirikuncar.github.io/sqlty/guide/row-types/)).
109
+
110
+ ### Wrong parameters, misspelled columns
111
+
112
+ ```toml
113
+ [tool.sqlty]
114
+ dialect = "sqlite"
115
+ schema = "schema.sql"
116
+
117
+ [tool.sqlty.rules]
118
+ unknown-column = "warn"
119
+ ```
120
+
121
+ `schema.sql`:
122
+
123
+ ```sql
124
+ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
125
+ ```
126
+
127
+ ```python
128
+ import sqlite3
129
+ from sqlty import SQL
130
+
131
+ conn = sqlite3.connect("app.db")
132
+
133
+ # error: [param-count-mismatch] "query has 1 parameter, the call passes 2"
134
+ conn.execute(SQL[tuple[str | None]]("--sql\nSELECT email FROM users WHERE id = ?"), (1, 2))
135
+
136
+ # error: [unknown-column] "column `emial` does not exist in `users`"
137
+ conn.execute("--sql\nSELECT emial FROM users")
138
+ ```
139
+
140
+ `?`, `$1`, `%s` and `:name` placeholders are checked on sqlite3, psycopg and
141
+ asyncpg calls ([Parameters](https://jirikuncar.github.io/sqlty/guide/parameters/)).
142
+ These are the mistakes coding agents make: every problem is one
143
+ `file:line: [rule] message` line and a non-zero exit code they can act on, and
144
+ the [sqlty skill](https://jirikuncar.github.io/sqlty/recipes/agents/) teaches
145
+ them the conventions.
146
+
147
+ ## Get started
148
+
149
+ ```bash
150
+ pip install "sqlty[psycopg]" # or: uv add sqlty; the extra adds the psycopg helpers
151
+ printf '%s\n' 'q = "--sql\nSELECT id::INTEGER, name::TEXT FROM users"' > queries.py
152
+ sqlty rewrite -v . # q = SQL[tuple[int, str]]("--sql\n...")
153
+ sqlty check . # report drift and mismatches
154
+ sqlty strip . # undo: back to plain strings
155
+ ```
156
+
157
+ `rewrite` and `strip` only touch the wrapper, never the SQL, so you can adopt
158
+ sqlty one module at a time and back out. New project:
159
+ [Quickstart](https://jirikuncar.github.io/sqlty/quickstart/). Existing codebase:
160
+ [Migration](https://jirikuncar.github.io/sqlty/recipes/migration/), starting
161
+ with `pg_dump --schema-only app > schema.sql`.
162
+
163
+ Not a fit for ORMs, SQL built at runtime, or runtime validation;
164
+ [Why SQLTy?](https://jirikuncar.github.io/sqlty/motivation/) compares it with
165
+ sqlc, sqlx, PgTyped and others.
166
+
167
+ ## About
168
+
169
+ The engine is Rust ([sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs)
170
+ via [PyO3](https://pyo3.rs)), with wheels for Linux, macOS and Windows. SQLTy is
171
+ developed with AI coding agents, mainly Claude Code; every change is reviewed by
172
+ a maintainer (see the
173
+ [AI-assisted contributions](https://github.com/jirikuncar/sqlty/blob/main/CONTRIBUTING.md#ai-assisted-contributions)
174
+ policy). [Contributing](https://github.com/jirikuncar/sqlty/blob/main/CONTRIBUTING.md) ·
175
+ [Credits](https://jirikuncar.github.io/sqlty/credits/) ·
176
+ MIT [License](https://github.com/jirikuncar/sqlty/blob/main/LICENSE).
@@ -0,0 +1,171 @@
1
+ [project]
2
+ name = "sqlty"
3
+ dynamic = ["version"]
4
+ description = "Type-safe SQL queries for Python"
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [{ name = "Jiri Kuncar", email = "jiri.kuncar@gmail.com" }]
10
+ keywords = [
11
+ "sql",
12
+ "type-hints",
13
+ "mypy",
14
+ "type-safety",
15
+ "static-analysis",
16
+ "code-generation",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Environment :: Console",
21
+ "Intended Audience :: Developers",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Programming Language :: Python :: 3.15",
26
+ "Programming Language :: Rust",
27
+ "Programming Language :: SQL",
28
+ "Topic :: Software Development :: Code Generators",
29
+ "Topic :: Software Development :: Libraries :: Python Modules",
30
+ "Topic :: Database",
31
+ "Typing :: Typed",
32
+ ]
33
+ dependencies = [
34
+ "pathspec>=0.12.1",
35
+ "typing-extensions>=4.15.0; python_version < '3.15'",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/jirikuncar/sqlty"
40
+ Documentation = "https://jirikuncar.github.io/sqlty/"
41
+ Repository = "https://github.com/jirikuncar/sqlty"
42
+ Changelog = "https://github.com/jirikuncar/sqlty/releases"
43
+ Issues = "https://github.com/jirikuncar/sqlty/issues"
44
+
45
+ [project.scripts]
46
+ sqlty = "sqlty._cli:main"
47
+
48
+ [project.optional-dependencies]
49
+ psycopg = ["psycopg>=3.2.12"]
50
+
51
+ [build-system]
52
+ requires = ["maturin>=1.12.1,<2.0"]
53
+ build-backend = "maturin"
54
+
55
+ [tool.maturin]
56
+ python-source = "src"
57
+ module-name = "sqlty._core"
58
+ features = ["pyo3/extension-module"]
59
+ manifest-path = "rust/crates/sqlty-ext/Cargo.toml"
60
+ # Ship the startup hook at the wheel root so it lands in site-packages and
61
+ # registers the lazy "sqlty" codec lookup (see docs/guide/magic-codec.md).
62
+ # The path is relative to the project root (maturin >= 1.12.1): the wheel gets
63
+ # it at the root (python-source prefix stripped), the sdist at src/.
64
+ include = ["src/sqlty_magic.pth"]
65
+
66
+ [dependency-groups]
67
+ dev = [
68
+ "inline-snapshot>=0.15.0",
69
+ "maturin>=1.12.1,<2.0",
70
+ "mypy>=2.4.0",
71
+ "prek>=0.5.4",
72
+ "pyright>=1.1.414",
73
+ "pytest>=8.4.2",
74
+ "pytest-cov>=6.0.0",
75
+ "pytest-randomly>=3.16.0",
76
+ "pyyaml>=6.0.2",
77
+ "ruff>=0.16.10",
78
+ "ty>=0.0.85",
79
+ "rumdl>=0.3.0",
80
+ "vale>=3.22.0.0",
81
+ "zizmor>=1.31.1",
82
+ ]
83
+ cli = ["rich>=15.0.0"]
84
+ # Only the DuckDB type tests need it, and it has no wheel for every Python.
85
+ duckdb = ["duckdb>=1.4.0"]
86
+ psycopg = ["psycopg>=3.2.12"]
87
+ fuzz = [
88
+ "hypothesis>=6.140",
89
+ ]
90
+
91
+ [tool.pytest.ini_options]
92
+ addopts = ["-p", "tests._mdtest.plugin", "--cov-report=term-missing", "--cov-report=html", "-v"]
93
+ pythonpath = ["."]
94
+ testpaths = ["tests", "docs", "src/sqlty/rules", "README.md"]
95
+ mdtest_paths = ["tests/mdtest", "docs", "src/sqlty/rules", "README.md", "skills"]
96
+ markers = [
97
+ "e2e: end-to-end tests (subprocess + inline-snapshot)",
98
+ "slow: slow tests that can be skipped with -m 'not slow'",
99
+ "pg: needs a PostgreSQL server (SQLTY_PG_DSN); skipped without it",
100
+ ]
101
+
102
+ [tool.coverage.run]
103
+ concurrency = ["multiprocessing"]
104
+ parallel = true
105
+ sigterm = true
106
+ patch = ["subprocess"]
107
+ omit = ["tests/*", "examples/*"]
108
+
109
+ [tool.coverage.paths]
110
+ source = ["src/"]
111
+
112
+ [tool.coverage.combine]
113
+ show_missing = true
114
+
115
+ [tool.mypy]
116
+ python_version = "3.15"
117
+ strict = true
118
+ warn_return_any = true
119
+ warn_unused_configs = true
120
+ disallow_untyped_defs = true
121
+ disallow_any_generics = true
122
+ check_untyped_defs = true
123
+ warn_redundant_casts = true
124
+ warn_unused_ignores = true
125
+ warn_no_return = true
126
+
127
+ [[tool.mypy.overrides]]
128
+ module = "psycopg.*"
129
+ ignore_missing_imports = true
130
+
131
+ [tool.ty.environment]
132
+ # Python version will be inferred from requires-python
133
+ root = ["./src", "./examples"]
134
+
135
+ [tool.ty.src]
136
+ include = ["src", "examples"]
137
+
138
+ [tool.ruff]
139
+ target-version = "py314"
140
+ line-length = 100
141
+ # Markdown code blocks are test data (mdtest, README) and must not be reformatted.
142
+ extend-exclude = ["tests/typechecks", "*.md"]
143
+
144
+ [tool.ruff.lint]
145
+ select = [
146
+ "E", # pycodestyle errors
147
+ "W", # pycodestyle warnings
148
+ "F", # pyflakes
149
+ "I", # isort
150
+ "UP", # pyupgrade
151
+ "B", # flake8-bugbear
152
+ "C4", # flake8-comprehensions
153
+ "SIM", # flake8-simplify
154
+ ]
155
+ ignore = [
156
+ "E501", # line too long (handled by formatter)
157
+ "SIM102", # nested if statements (can be more readable)
158
+ ]
159
+
160
+ [tool.ruff.format]
161
+ quote-style = "double"
162
+ indent-style = "space"
163
+
164
+ [tool.rumdl]
165
+ # Long lines are tables and links; spaces in code spans show `--sql ` on purpose.
166
+ disable = ["MD013", "MD038"]
167
+ exclude = ["site", ".vale", ".github", "tests", "scripts/compat/reports", "PLAN-FUTURE.md", "rust/target", "proofs/.lake"]
168
+
169
+ [tool.rumdl.per-file-ignores]
170
+ # The demo GIF needs HTML for its width and centering.
171
+ "README.md" = ["MD033"]