syntopica-codeality-py 0.2.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 (199) hide show
  1. syntopica_codeality_py-0.2.0/.gitignore +44 -0
  2. syntopica_codeality_py-0.2.0/CHANGELOG.md +222 -0
  3. syntopica_codeality_py-0.2.0/LICENSE +21 -0
  4. syntopica_codeality_py-0.2.0/PKG-INFO +96 -0
  5. syntopica_codeality_py-0.2.0/README.md +53 -0
  6. syntopica_codeality_py-0.2.0/codeality-py.toml +27 -0
  7. syntopica_codeality_py-0.2.0/mypy.ini +10 -0
  8. syntopica_codeality_py-0.2.0/pyproject.toml +60 -0
  9. syntopica_codeality_py-0.2.0/ruff.toml +51 -0
  10. syntopica_codeality_py-0.2.0/src/codeality_py/__init__.py +1 -0
  11. syntopica_codeality_py-0.2.0/src/codeality_py/assets/codeality-py-ci.yml +51 -0
  12. syntopica_codeality_py-0.2.0/src/codeality_py/assets/codeality-py.toml +19 -0
  13. syntopica_codeality_py-0.2.0/src/codeality_py/assets/importlinter.ini +12 -0
  14. syntopica_codeality_py-0.2.0/src/codeality_py/assets/mypy.ini +7 -0
  15. syntopica_codeality_py-0.2.0/src/codeality_py/assets/pyproject-sections.toml +34 -0
  16. syntopica_codeality_py-0.2.0/src/codeality_py/assets/ruff.toml +51 -0
  17. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/__init__.py +1 -0
  18. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/baseline_file.py +15 -0
  19. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/classified_findings.py +14 -0
  20. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/classify_findings.py +18 -0
  21. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/finding_context.py +19 -0
  22. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/fingerprint.py +21 -0
  23. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/fingerprint_context.py +27 -0
  24. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/read_baseline.py +32 -0
  25. syntopica_codeality_py-0.2.0/src/codeality_py/baseline/write_baseline.py +18 -0
  26. syntopica_codeality_py-0.2.0/src/codeality_py/cli.py +22 -0
  27. syntopica_codeality_py-0.2.0/src/codeality_py/commands/__init__.py +1 -0
  28. syntopica_codeality_py-0.2.0/src/codeality_py/commands/baseline_check_command.py +36 -0
  29. syntopica_codeality_py-0.2.0/src/codeality_py/commands/baseline_command.py +15 -0
  30. syntopica_codeality_py-0.2.0/src/codeality_py/commands/baseline_update_command.py +24 -0
  31. syntopica_codeality_py-0.2.0/src/codeality_py/commands/check_command.py +45 -0
  32. syntopica_codeality_py-0.2.0/src/codeality_py/commands/checked_project.py +26 -0
  33. syntopica_codeality_py-0.2.0/src/codeality_py/commands/gate_command.py +33 -0
  34. syntopica_codeality_py-0.2.0/src/codeality_py/commands/init_command.py +53 -0
  35. syntopica_codeality_py-0.2.0/src/codeality_py/commands/project_option.py +12 -0
  36. syntopica_codeality_py-0.2.0/src/codeality_py/config/__init__.py +1 -0
  37. syntopica_codeality_py-0.2.0/src/codeality_py/config/baseline_config.py +27 -0
  38. syntopica_codeality_py-0.2.0/src/codeality_py/config/check_schema_version.py +16 -0
  39. syntopica_codeality_py-0.2.0/src/codeality_py/config/config_error.py +5 -0
  40. syntopica_codeality_py-0.2.0/src/codeality_py/config/default_generated_globs.py +10 -0
  41. syntopica_codeality_py-0.2.0/src/codeality_py/config/discover_source_roots.py +30 -0
  42. syntopica_codeality_py-0.2.0/src/codeality_py/config/discover_test_roots.py +12 -0
  43. syntopica_codeality_py-0.2.0/src/codeality_py/config/limits.py +11 -0
  44. syntopica_codeality_py-0.2.0/src/codeality_py/config/load_config.py +64 -0
  45. syntopica_codeality_py-0.2.0/src/codeality_py/config/module_role.py +18 -0
  46. syntopica_codeality_py-0.2.0/src/codeality_py/config/override.py +14 -0
  47. syntopica_codeality_py-0.2.0/src/codeality_py/config/parse_overrides.py +32 -0
  48. syntopica_codeality_py-0.2.0/src/codeality_py/config/parse_roles.py +33 -0
  49. syntopica_codeality_py-0.2.0/src/codeality_py/config/parse_rule_codes.py +17 -0
  50. syntopica_codeality_py-0.2.0/src/codeality_py/config/pyproject_layout_hints.py +36 -0
  51. syntopica_codeality_py-0.2.0/src/codeality_py/config/read_config_document.py +17 -0
  52. syntopica_codeality_py-0.2.0/src/codeality_py/config/reject_duplicate_role_claims.py +20 -0
  53. syntopica_codeality_py-0.2.0/src/codeality_py/config/reject_unknown_keys.py +15 -0
  54. syntopica_codeality_py-0.2.0/src/codeality_py/engine/__init__.py +1 -0
  55. syntopica_codeality_py-0.2.0/src/codeality_py/engine/check_project.py +32 -0
  56. syntopica_codeality_py-0.2.0/src/codeality_py/engine/check_result.py +15 -0
  57. syntopica_codeality_py-0.2.0/src/codeality_py/engine/check_source_file.py +25 -0
  58. syntopica_codeality_py-0.2.0/src/codeality_py/engine/fingerprint_findings.py +33 -0
  59. syntopica_codeality_py-0.2.0/src/codeality_py/engine/rule_registry.py +24 -0
  60. syntopica_codeality_py-0.2.0/src/codeality_py/gate/__init__.py +1 -0
  61. syntopica_codeality_py-0.2.0/src/codeality_py/gate/build_stage_result.py +20 -0
  62. syntopica_codeality_py-0.2.0/src/codeality_py/gate/gate_result.py +23 -0
  63. syntopica_codeality_py-0.2.0/src/codeality_py/gate/gate_stages.py +50 -0
  64. syntopica_codeality_py-0.2.0/src/codeality_py/gate/run_gate.py +27 -0
  65. syntopica_codeality_py-0.2.0/src/codeality_py/gate/run_stage.py +52 -0
  66. syntopica_codeality_py-0.2.0/src/codeality_py/gate/stage.py +14 -0
  67. syntopica_codeality_py-0.2.0/src/codeality_py/gate/stage_kind.py +11 -0
  68. syntopica_codeality_py-0.2.0/src/codeality_py/gate/stage_result.py +19 -0
  69. syntopica_codeality_py-0.2.0/src/codeality_py/gate/stage_status.py +12 -0
  70. syntopica_codeality_py-0.2.0/src/codeality_py/init/__init__.py +1 -0
  71. syntopica_codeality_py-0.2.0/src/codeality_py/init/add_missing_rules.py +33 -0
  72. syntopica_codeality_py-0.2.0/src/codeality_py/init/apply_init.py +19 -0
  73. syntopica_codeality_py-0.2.0/src/codeality_py/init/current_branch.py +24 -0
  74. syntopica_codeality_py-0.2.0/src/codeality_py/init/first_party_packages.py +23 -0
  75. syntopica_codeality_py-0.2.0/src/codeality_py/init/has_ruff_table.py +21 -0
  76. syntopica_codeality_py-0.2.0/src/codeality_py/init/managed_asset_files.py +9 -0
  77. syntopica_codeality_py-0.2.0/src/codeality_py/init/managed_file.py +16 -0
  78. syntopica_codeality_py-0.2.0/src/codeality_py/init/merge_pyproject_sections.py +35 -0
  79. syntopica_codeality_py-0.2.0/src/codeality_py/init/merge_quality_group.py +14 -0
  80. syntopica_codeality_py-0.2.0/src/codeality_py/init/merge_ruff_config.py +28 -0
  81. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_asset_file.py +25 -0
  82. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_disposition.py +12 -0
  83. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_init.py +28 -0
  84. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_pyproject.py +32 -0
  85. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_ruff.py +21 -0
  86. syntopica_codeality_py-0.2.0/src/codeality_py/init/plan_shadowed_ruff.py +28 -0
  87. syntopica_codeality_py-0.2.0/src/codeality_py/init/python_floor_minor.py +15 -0
  88. syntopica_codeality_py-0.2.0/src/codeality_py/init/read_asset.py +8 -0
  89. syntopica_codeality_py-0.2.0/src/codeality_py/init/read_requires_python.py +16 -0
  90. syntopica_codeality_py-0.2.0/src/codeality_py/init/render_asset.py +55 -0
  91. syntopica_codeality_py-0.2.0/src/codeality_py/init/render_nested_workflow.py +25 -0
  92. syntopica_codeality_py-0.2.0/src/codeality_py/init/repository_root.py +15 -0
  93. syntopica_codeality_py-0.2.0/src/codeality_py/init/workflow_target.py +21 -0
  94. syntopica_codeality_py-0.2.0/src/codeality_py/model/__init__.py +1 -0
  95. syntopica_codeality_py-0.2.0/src/codeality_py/model/finding.py +34 -0
  96. syntopica_codeality_py-0.2.0/src/codeality_py/model/location.py +14 -0
  97. syntopica_codeality_py-0.2.0/src/codeality_py/model/rule_code.py +30 -0
  98. syntopica_codeality_py-0.2.0/src/codeality_py/model/severity.py +10 -0
  99. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/__init__.py +1 -0
  100. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/infrastructure_error.py +5 -0
  101. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/parse_source_file.py +32 -0
  102. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/read_source_text.py +16 -0
  103. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/source_file.py +18 -0
  104. syntopica_codeality_py-0.2.0/src/codeality_py/parsing/syntax_error_finding.py +16 -0
  105. syntopica_codeality_py-0.2.0/src/codeality_py/report/__init__.py +1 -0
  106. syntopica_codeality_py-0.2.0/src/codeality_py/report/exit_code.py +12 -0
  107. syntopica_codeality_py-0.2.0/src/codeality_py/report/finding_document.py +24 -0
  108. syntopica_codeality_py-0.2.0/src/codeality_py/report/findings_summary.py +11 -0
  109. syntopica_codeality_py-0.2.0/src/codeality_py/report/render_gate_report.py +21 -0
  110. syntopica_codeality_py-0.2.0/src/codeality_py/report/render_json_report.py +24 -0
  111. syntopica_codeality_py-0.2.0/src/codeality_py/report/render_text_report.py +16 -0
  112. syntopica_codeality_py-0.2.0/src/codeality_py/report/stage_document.py +16 -0
  113. syntopica_codeality_py-0.2.0/src/codeality_py/roles/__init__.py +1 -0
  114. syntopica_codeality_py-0.2.0/src/codeality_py/roles/assign_module_role.py +36 -0
  115. syntopica_codeality_py-0.2.0/src/codeality_py/roles/compile_glob.py +17 -0
  116. syntopica_codeality_py-0.2.0/src/codeality_py/roles/matches_any_pattern.py +8 -0
  117. syntopica_codeality_py-0.2.0/src/codeality_py/roles/matches_glob.py +14 -0
  118. syntopica_codeality_py-0.2.0/src/codeality_py/roles/test_file_patterns.py +18 -0
  119. syntopica_codeality_py-0.2.0/src/codeality_py/rules/__init__.py +1 -0
  120. syntopica_codeality_py-0.2.0/src/codeality_py/rules/barrel_only_init.py +38 -0
  121. syntopica_codeality_py-0.2.0/src/codeality_py/rules/count_code_lines.py +29 -0
  122. syntopica_codeality_py-0.2.0/src/codeality_py/rules/data_unit_findings.py +16 -0
  123. syntopica_codeality_py-0.2.0/src/codeality_py/rules/docstring_line_spans.py +26 -0
  124. syntopica_codeality_py-0.2.0/src/codeality_py/rules/file_matches_unit.py +33 -0
  125. syntopica_codeality_py-0.2.0/src/codeality_py/rules/grab_bag_names.py +3 -0
  126. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_allowed_barrel_statement.py +16 -0
  127. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_column_list.py +15 -0
  128. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_docstring_statement.py +12 -0
  129. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_sql_literal.py +15 -0
  130. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_static_dunder_assignment.py +24 -0
  131. syntopica_codeality_py-0.2.0/src/codeality_py/rules/is_type_checking_block.py +15 -0
  132. syntopica_codeality_py-0.2.0/src/codeality_py/rules/joined_string_text.py +12 -0
  133. syntopica_codeality_py-0.2.0/src/codeality_py/rules/looks_like_sql.py +31 -0
  134. syntopica_codeality_py-0.2.0/src/codeality_py/rules/max_file_lines.py +35 -0
  135. syntopica_codeality_py-0.2.0/src/codeality_py/rules/no_grab_bag_names.py +36 -0
  136. syntopica_codeality_py-0.2.0/src/codeality_py/rules/no_inline_sql.py +52 -0
  137. syntopica_codeality_py-0.2.0/src/codeality_py/rules/one_primary_unit.py +22 -0
  138. syntopica_codeality_py-0.2.0/src/codeality_py/rules/ordinary_unit_findings.py +26 -0
  139. syntopica_codeality_py-0.2.0/src/codeality_py/rules/sql_subject.py +10 -0
  140. syntopica_codeality_py-0.2.0/src/codeality_py/rules/unit_finding.py +23 -0
  141. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/__init__.py +1 -0
  142. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/apply_suppressions.py +31 -0
  143. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/build_suppression.py +15 -0
  144. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/covering_suppression.py +25 -0
  145. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/is_overridden.py +14 -0
  146. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/parse_suppression_line.py +25 -0
  147. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/parse_suppressions.py +17 -0
  148. syntopica_codeality_py-0.2.0/src/codeality_py/suppression/suppression.py +14 -0
  149. syntopica_codeality_py-0.2.0/src/codeality_py/traversal/__init__.py +1 -0
  150. syntopica_codeality_py-0.2.0/src/codeality_py/traversal/collect_source_files.py +17 -0
  151. syntopica_codeality_py-0.2.0/src/codeality_py/traversal/default_excludes.py +25 -0
  152. syntopica_codeality_py-0.2.0/src/codeality_py/traversal/gitignore_matcher.py +44 -0
  153. syntopica_codeality_py-0.2.0/src/codeality_py/traversal/walk_root.py +27 -0
  154. syntopica_codeality_py-0.2.0/src/codeality_py/units/__init__.py +1 -0
  155. syntopica_codeality_py-0.2.0/src/codeality_py/units/coalesce_overloads.py +17 -0
  156. syntopica_codeality_py-0.2.0/src/codeality_py/units/coalesce_singledispatch.py +25 -0
  157. syntopica_codeality_py-0.2.0/src/codeality_py/units/collect_declarations.py +15 -0
  158. syntopica_codeality_py-0.2.0/src/codeality_py/units/count_primary_declarations.py +18 -0
  159. syntopica_codeality_py-0.2.0/src/codeality_py/units/declaration.py +18 -0
  160. syntopica_codeality_py-0.2.0/src/codeality_py/units/declaration_for.py +33 -0
  161. syntopica_codeality_py-0.2.0/src/codeality_py/units/declaration_kind.py +11 -0
  162. syntopica_codeality_py-0.2.0/src/codeality_py/units/decorator_name.py +14 -0
  163. syntopica_codeality_py-0.2.0/src/codeality_py/units/decorator_names.py +12 -0
  164. syntopica_codeality_py-0.2.0/src/codeality_py/units/is_main_guard.py +11 -0
  165. syntopica_codeality_py-0.2.0/src/codeality_py/units/is_private_local_handler.py +13 -0
  166. syntopica_codeality_py-0.2.0/src/codeality_py/units/legacy_type_alias.py +33 -0
  167. syntopica_codeality_py-0.2.0/src/codeality_py/units/literal_string_names.py +15 -0
  168. syntopica_codeality_py-0.2.0/src/codeality_py/units/merge_stray_letters.py +20 -0
  169. syntopica_codeality_py-0.2.0/src/codeality_py/units/named_declaration.py +23 -0
  170. syntopica_codeality_py-0.2.0/src/codeality_py/units/overload_family_length.py +22 -0
  171. syntopica_codeality_py-0.2.0/src/codeality_py/units/resolve_exported_names.py +22 -0
  172. syntopica_codeality_py-0.2.0/src/codeality_py/units/to_snake_case.py +20 -0
  173. syntopica_codeality_py-0.2.0/src/codeality_py/units/top_level_statements.py +20 -0
  174. syntopica_codeality_py-0.2.0/tests/baseline/test_classify_findings.py +111 -0
  175. syntopica_codeality_py-0.2.0/tests/commands/test_baseline_command.py +67 -0
  176. syntopica_codeality_py-0.2.0/tests/commands/test_check_command.py +77 -0
  177. syntopica_codeality_py-0.2.0/tests/config/test_load_config.py +88 -0
  178. syntopica_codeality_py-0.2.0/tests/config/test_pyproject_layout_hints.py +52 -0
  179. syntopica_codeality_py-0.2.0/tests/conftest.py +35 -0
  180. syntopica_codeality_py-0.2.0/tests/gate/test_gate_stages.py +69 -0
  181. syntopica_codeality_py-0.2.0/tests/gate/test_run_gate.py +85 -0
  182. syntopica_codeality_py-0.2.0/tests/init/test_merge_ruff_config.py +49 -0
  183. syntopica_codeality_py-0.2.0/tests/init/test_plan_init.py +172 -0
  184. syntopica_codeality_py-0.2.0/tests/init/test_render_asset.py +132 -0
  185. syntopica_codeality_py-0.2.0/tests/model/test_finding.py +27 -0
  186. syntopica_codeality_py-0.2.0/tests/model/test_rule_code.py +12 -0
  187. syntopica_codeality_py-0.2.0/tests/parsing/test_parse_source_file.py +42 -0
  188. syntopica_codeality_py-0.2.0/tests/roles/test_assign_module_role.py +72 -0
  189. syntopica_codeality_py-0.2.0/tests/roles/test_matches_glob.py +38 -0
  190. syntopica_codeality_py-0.2.0/tests/rules/test_barrel_only_init.py +69 -0
  191. syntopica_codeality_py-0.2.0/tests/rules/test_file_matches_unit.py +41 -0
  192. syntopica_codeality_py-0.2.0/tests/rules/test_max_file_lines.py +53 -0
  193. syntopica_codeality_py-0.2.0/tests/rules/test_no_grab_bag_names.py +37 -0
  194. syntopica_codeality_py-0.2.0/tests/rules/test_no_inline_sql.py +71 -0
  195. syntopica_codeality_py-0.2.0/tests/rules/test_one_primary_unit.py +209 -0
  196. syntopica_codeality_py-0.2.0/tests/test_cli_version.py +11 -0
  197. syntopica_codeality_py-0.2.0/tests/traversal/test_collect_source_files.py +78 -0
  198. syntopica_codeality_py-0.2.0/tests/units/test_to_snake_case.py +23 -0
  199. syntopica_codeality_py-0.2.0/uv.lock +1061 -0
@@ -0,0 +1,44 @@
1
+ node_modules/
2
+ .pnpm-store/
3
+ **/.astro/
4
+ **/.next/
5
+ **/.nuxt/
6
+ **/.output/
7
+ **/dist/
8
+ **/build/
9
+ **/coverage/
10
+ **/*.tsbuildinfo
11
+ **/.lighthouseci/
12
+ # Written per workspace by scripts/deps-graph-aliased.mjs and removed again on
13
+ # the way out; ignored so a crashed run cannot leave a tracked file behind.
14
+ **/.baseline-depcruise.tsconfig.json
15
+ **/.turbo/
16
+ .turbo/
17
+ .DS_Store
18
+ # CocoIndex Code (ccc)
19
+ /.cocoindex_code/
20
+ # Codegraph local index
21
+ /.codegraph/
22
+
23
+ # Serena (local tool state)
24
+ .serena/
25
+
26
+ target/
27
+
28
+ # eslint-suppressions.json is deliberately committed: it is the shared
29
+ # frozen baseline of pre-existing violations.
30
+
31
+ # Stryker's mutant sandbox and HTML report
32
+ .stryker-tmp/
33
+ reports/mutation/
34
+
35
+ # Python (packages/codeality-py, templates/python-package)
36
+ **/.venv/
37
+ **/__pycache__/
38
+ **/.pytest_cache/
39
+ **/.mypy_cache/
40
+ **/.ruff_cache/
41
+ **/*.egg-info/
42
+
43
+ # coverage.py writes its SQLite database beside the tests it measured.
44
+ .coverage
@@ -0,0 +1,222 @@
1
+ # Changelog
2
+
3
+ All notable changes to `syntopica-codeality-py` are documented here. The format
4
+ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## 0.2.0
8
+
9
+ ### Changed
10
+
11
+ - Renamed everywhere: the distribution is `syntopica-codeality-py`, the import
12
+ package is `codeality_py`, the console script is `codeality-py`, and the
13
+ configuration file is `codeality-py.toml`. The old `busirocket-baseline-py`
14
+ releases stay on PyPI and receive no further updates.
15
+ - The inline suppression prefix is now `# codeality-py: ignore[...]` and
16
+ `# codeality-py: ignore-file[...]`. Rule codes keep the `BPY` prefix: codes
17
+ are permanent identifiers and never change meaning.
18
+
19
+ ### Migration
20
+
21
+ - Replace the dependency, rename `baseline-py.toml` to `codeality-py.toml`,
22
+ rewrite any `# baseline-py:` suppression comment, and change
23
+ `uv run baseline-py gate` to `uv run codeality-py gate` in CI.
24
+
25
+ ## 0.1.12
26
+
27
+ ### Fixed
28
+
29
+ - A failing stage's detail now carries its stderr as well as its stdout. deptry
30
+ reports on stderr, so a red deptry stage in CI showed an exit code and an
31
+ empty detail, and the reader had nothing to act on.
32
+
33
+ ## 0.1.11
34
+
35
+ ### Fixed
36
+
37
+ - An f-string holding SQL is one `BPY006` finding, reported at the string. Its
38
+ constant parts were reported too, and their positions differ between Python
39
+ 3.11 and 3.12, so the same query fingerprinted differently depending on the
40
+ interpreter: a baseline recorded on 3.13 reported one new and one resolved
41
+ finding on a 3.11 runner.
42
+ - `init --ci` in a project nested inside a repository writes the workflow at the
43
+ repository root, named `quality-<project>.yml`, with every step running from
44
+ the project directory. GitHub reads workflows only from the root, so the file
45
+ scaffolded inside `tools/qlctool` was never picked up.
46
+
47
+ ## 0.1.10
48
+
49
+ ### Fixed
50
+
51
+ - The scaffolded workflow listens on the branch the project is checked out on
52
+ instead of always `main`. Two of the first eight adopters lived on `master`
53
+ and on a feature branch, and a workflow watching `main` never ran for either;
54
+ a nested project reads the enclosing repository's branch.
55
+
56
+ ## 0.1.9
57
+
58
+ ### Fixed
59
+
60
+ - `init` no longer rewrites a consumer's `[tool.ruff.lint]` `select` and
61
+ `ignore` arrays when merging. The old merge rebuilt each array as a sorted
62
+ set, which kept every code and dropped every comment - and a consumer's ignore
63
+ list is usually a dated ledger of adoption debt, one family per line with the
64
+ count found. The arrays are now extended in place: missing codes land on one
65
+ new line, marked, and nothing else moves. A project with nothing missing is
66
+ reported `unchanged`.
67
+ - The scaffolded CI matrix and ruff `target-version` follow the project's
68
+ `requires-python` floor instead of a hard-coded 3.11. A matrix cell below the
69
+ floor failed on `uv sync` before the gate ran; a ruff target below it let
70
+ pyupgrade stop short of the syntax the project may already use.
71
+
72
+ ### Changed
73
+
74
+ - The scaffolded workflow installs with
75
+ `uv sync --locked --all-extras --all-groups`, so CI audits and tests the same
76
+ environment a local `uv run codeality-py gate` does; a group-only install left
77
+ out the extras the tests import. Its actions are pinned by commit SHA.
78
+ - The shipped `mypy.ini` no longer carries a `[mypy-tests.*]` section. The
79
+ gate's mypy stage checks source roots only, so the section relaxed nothing;
80
+ configuration should not promise what the gate does not do.
81
+
82
+ ## 0.1.8
83
+
84
+ ### Added
85
+
86
+ - `init` now reports a `ruff.toml` sitting beside a pyproject that also declares
87
+ `[tool.ruff]`. Ruff reads one configuration per directory, so the file wins
88
+ outright and the table is never read - silently. The pair builds itself over
89
+ time: init writes the file when no table exists, and a table arrives later.
90
+ Found in DJCenterDeluxe, which spent a release linting against a config nobody
91
+ read; once the shadow was removed, 1707 findings resolved to 6 real ones.
92
+
93
+ ### Changed
94
+
95
+ - The shipped deptry ignores gained `DEP004` defaults for the pytest family:
96
+ test tooling legitimately lives in a dev group and is imported only by tests.
97
+
98
+ ## 0.1.7
99
+
100
+ ### Changed
101
+
102
+ - A missing shadow-stage tool is now `skipped-not-applicable` instead of
103
+ `failed-to-run`. A required tool that cannot run is still a failure; an
104
+ advisory tool that was never installed is not an alarm.
105
+ - `init` no longer adds the quality dependency group to a project whose
106
+ `requires-python` floor is below 3.11: the group carries
107
+ `syntopica-codeality-py`, and declaring it there makes every uv resolution
108
+ unsatisfiable. Found adopting the baseline in `djplayerdeluxe`, which declares
109
+ `>=3.8` for its Raspberry Pi target.
110
+
111
+ ## 0.1.6
112
+
113
+ ### Added
114
+
115
+ - `[audit] ignore-vulns` in `codeality-py.toml`: accepted advisories, each
116
+ expected to carry a written reason, reach pip-audit as `--ignore-vuln` flags.
117
+ Found adopting the baseline in `clawd-pet`, where platformio 6.x pins
118
+ starlette below the patched release and the gate had no way to accept the
119
+ documented risk.
120
+ - `init` records the discovered `import-package`, so coverage measures the
121
+ package instead of a source directory path.
122
+
123
+ ### Changed
124
+
125
+ - Tests' per-file-ignores grew `S105`, `S106`, `S108` (fixtures hold dummy
126
+ tokens and /tmp sockets) and now ignore the whole `PLR` family (a test factory
127
+ with seven keywords is a fixture, not a design smell).
128
+
129
+ ## 0.1.5
130
+
131
+ ### Changed
132
+
133
+ - Root discovery now reads the layout a `pyproject.toml` already declares -
134
+ pytest's `pythonpath` and `testpaths`, hatch's wheel `packages` - before
135
+ guessing from directories. Found adopting the baseline in `clawd-pet`, a
136
+ firmware host whose Python lives under `host/src` where directory scanning
137
+ sees nothing.
138
+ - The test per-file-ignores pattern is `**/tests/**`, so it also reaches nested
139
+ test roots such as `host/tests`.
140
+ - `D107` joined the ignore list: an `__init__` that stores its arguments has
141
+ nothing to add to the class docstring.
142
+
143
+ ### Fixed
144
+
145
+ - The package now passes its own `init`-scaffolded configuration - it had been
146
+ gating itself with ruff's and mypy's defaults instead of the strict config it
147
+ ships, because no `ruff.toml` or `mypy.ini` existed in the repository.
148
+
149
+ ## 0.1.4
150
+
151
+ ### Fixed
152
+
153
+ - The gate's structural stage now honors a recorded baseline: when
154
+ `.codeality-py-baseline.json` exists it runs `codeality-py baseline check`
155
+ instead of the bare `check`, so recording debt can actually turn the gate
156
+ green. Found adopting the baseline in `atrium`, where 61 recorded findings
157
+ still failed the gate.
158
+ - Merging into an existing `[tool.ruff]` no longer drops the per-file test
159
+ ignores and the pydocstyle convention the standalone `ruff.toml` always
160
+ carried. A project that already had a ruff table was held to docstring rules
161
+ in its tests that a fresh project was not.
162
+ - The shipped `codeality-py.toml` now carries `coverage-threshold = 80`, which
163
+ the dogfooded config always had and the asset silently lacked.
164
+
165
+ ## 0.1.3
166
+
167
+ ### Changed
168
+
169
+ - Python 3.11 is now supported. `ast.TypeAlias` handling degrades gracefully: on
170
+ 3.11 the PEP 695 syntax cannot parse at all, so nothing is lost. Found
171
+ adopting the baseline in `atrium`, whose `requires-python = ">=3.11"` made the
172
+ quality group unresolvable.
173
+ - `init` now discovers what it used to ask for: `source-roots` in
174
+ `codeality-py.toml`, `known_first_party` for deptry, and the import-linter
175
+ root package are filled from the project's real layout instead of `src` and
176
+ `CHANGE_ME` placeholders. The placeholder survives only when nothing is
177
+ discoverable.
178
+
179
+ ## 0.1.2
180
+
181
+ ### Fixed
182
+
183
+ - Baseline fingerprints no longer collapse several violations of one rule in one
184
+ file into a single entry, which let a fixed finding pay for a new one.
185
+ Identity is now decided per rule: a file-level rule (`BPY001`, `BPY004`)
186
+ identifies itself, a naming rule (`BPY002`, `BPY003`) identifies its symbol,
187
+ and everything else uses the offending line's content plus an occurrence
188
+ counter, so it survives edits elsewhere in the file. Found adopting the
189
+ baseline in DJCenterDeluxe, where 155 findings recorded as only 91 entries.
190
+
191
+ ## 0.1.1
192
+
193
+ ### Fixed
194
+
195
+ - Glob patterns now mean what they do everywhere else: `*` stops at a directory
196
+ separator and `**` crosses it. They were matched with `fnmatch`, whose `*`
197
+ crosses separators, so a role or override written for the scripts in a
198
+ repository root silently claimed every file in the tree. Found while adopting
199
+ the baseline in DJCenterDeluxe, where `entrypoint = ["*.py"]` matched all 106
200
+ files instead of the 40 at the root and hid 25 real `BPY002` findings.
201
+
202
+ ## 0.1.0
203
+
204
+ Initial release.
205
+
206
+ ### Added
207
+
208
+ - `codeality-py check`: six structural rules no ruff rule covers, over module
209
+ roles assigned before any file is parsed.
210
+ - `BPY000` parse-error, `BPY001` one-primary-unit, `BPY002` file-matches-unit,
211
+ `BPY003` no-grab-bag-names, `BPY004` max-file-lines, `BPY005`
212
+ barrel-only-init, `BPY006` no-inline-sql.
213
+ - Text and versioned JSON output, four exit codes, inline and configured
214
+ suppressions. The command never writes.
215
+ - `codeality-py init`: scaffolds ruff, mypy, deptry, pytest, coverage and CI
216
+ configuration by merging into what a project already has. A project that
217
+ configures ruff gets its `[tool.ruff]` extended, never a `ruff.toml` that
218
+ would silently take precedence over it.
219
+ - `codeality-py gate`: runs the whole quality chain. A required tool that is not
220
+ installed fails the gate rather than being skipped.
221
+ - `codeality-py baseline update|check`: records migration debt by content
222
+ fingerprint, reports new, known and resolved findings.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) BusiRocket
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.5
2
+ Name: syntopica-codeality-py
3
+ Version: 0.2.0
4
+ Summary: Structural linter and config scaffolder for Python: atomic files, placement, size caps, no inline SQL
5
+ Project-URL: Homepage, https://github.com/syntopica/codeality
6
+ Project-URL: Issues, https://github.com/syntopica/codeality/issues
7
+ Author: Cristian Deluxe
8
+ License: MIT License
9
+
10
+ Copyright (c) BusiRocket
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Keywords: architecture,ast,code-quality,linter
31
+ Classifier: Development Status :: 3 - Alpha
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Classifier: Topic :: Software Development :: Quality Assurance
39
+ Requires-Python: >=3.11
40
+ Requires-Dist: click<9,>=8.1
41
+ Requires-Dist: tomlkit<1,>=0.13
42
+ Description-Content-Type: text/markdown
43
+
44
+ # codeality-py
45
+
46
+ Structural linter and config scaffolder for Python: atomic files, placement,
47
+ size caps, no inline SQL. Brings the same discipline as
48
+ `@syntopica/eslint-config` and `cargo-baseline` to Python projects.
49
+
50
+ - **Design spec:**
51
+ [docs/superpowers/specs/2026-08-31-python-baseline-design.md](https://github.com/syntopica/codeality/blob/main/docs/superpowers/specs/2026-08-31-python-baseline-design.md).
52
+
53
+ ## Install
54
+
55
+ ```bash
56
+ uv add --dev syntopica-codeality-py
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ ```bash
62
+ codeality-py init [--check|--apply|--force] # scaffold ruff, mypy, deptry,
63
+ # pytest, coverage and CI config
64
+ codeality-py check [PATH...] # run the structural rules
65
+ codeality-py gate # run the whole quality chain
66
+ codeality-py baseline create|update|check # track migration debt
67
+ ```
68
+
69
+ `init` never overwrites: it merges into existing configuration, or reports a
70
+ conflict. `check` never writes. `gate` fails when a required tool is absent
71
+ rather than skipping it.
72
+
73
+ ## Rules
74
+
75
+ | Code | Rule | Enforces |
76
+ | -------- | ------------------- | -------------------------------------------------------------- |
77
+ | `BPY000` | `parse-error` | A file that fails to parse is a finding, never a silent skip. |
78
+ | `BPY001` | `one-primary-unit` | Exactly one primary declaration per ordinary module. |
79
+ | `BPY002` | `file-matches-unit` | File name is the snake_case of its primary declaration. |
80
+ | `BPY003` | `no-grab-bag-names` | No `utils`, `helpers`, `misc` or `common` in any path segment. |
81
+ | `BPY004` | `max-file-lines` | Code-line cap per file; tests get their own, looser cap. |
82
+ | `BPY005` | `barrel-only-init` | `__init__.py` holds imports, `__all__` and nothing else. |
83
+ | `BPY006` | `no-inline-sql` | SQL lives in resource files, not in string literals. |
84
+
85
+ ## Exit codes
86
+
87
+ | Code | Meaning |
88
+ | ---- | --------------------------------------------------------------- |
89
+ | 0 | All blocking checks passed. |
90
+ | 1 | Policy findings. |
91
+ | 2 | Invalid usage or invalid configuration. |
92
+ | 3 | Infrastructure failure: a required tool is missing or unusable. |
93
+
94
+ ## License
95
+
96
+ MIT
@@ -0,0 +1,53 @@
1
+ # codeality-py
2
+
3
+ Structural linter and config scaffolder for Python: atomic files, placement,
4
+ size caps, no inline SQL. Brings the same discipline as
5
+ `@syntopica/eslint-config` and `cargo-baseline` to Python projects.
6
+
7
+ - **Design spec:**
8
+ [docs/superpowers/specs/2026-08-31-python-baseline-design.md](https://github.com/syntopica/codeality/blob/main/docs/superpowers/specs/2026-08-31-python-baseline-design.md).
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ uv add --dev syntopica-codeality-py
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```bash
19
+ codeality-py init [--check|--apply|--force] # scaffold ruff, mypy, deptry,
20
+ # pytest, coverage and CI config
21
+ codeality-py check [PATH...] # run the structural rules
22
+ codeality-py gate # run the whole quality chain
23
+ codeality-py baseline create|update|check # track migration debt
24
+ ```
25
+
26
+ `init` never overwrites: it merges into existing configuration, or reports a
27
+ conflict. `check` never writes. `gate` fails when a required tool is absent
28
+ rather than skipping it.
29
+
30
+ ## Rules
31
+
32
+ | Code | Rule | Enforces |
33
+ | -------- | ------------------- | -------------------------------------------------------------- |
34
+ | `BPY000` | `parse-error` | A file that fails to parse is a finding, never a silent skip. |
35
+ | `BPY001` | `one-primary-unit` | Exactly one primary declaration per ordinary module. |
36
+ | `BPY002` | `file-matches-unit` | File name is the snake_case of its primary declaration. |
37
+ | `BPY003` | `no-grab-bag-names` | No `utils`, `helpers`, `misc` or `common` in any path segment. |
38
+ | `BPY004` | `max-file-lines` | Code-line cap per file; tests get their own, looser cap. |
39
+ | `BPY005` | `barrel-only-init` | `__init__.py` holds imports, `__all__` and nothing else. |
40
+ | `BPY006` | `no-inline-sql` | SQL lives in resource files, not in string literals. |
41
+
42
+ ## Exit codes
43
+
44
+ | Code | Meaning |
45
+ | ---- | --------------------------------------------------------------- |
46
+ | 0 | All blocking checks passed. |
47
+ | 1 | Policy findings. |
48
+ | 2 | Invalid usage or invalid configuration. |
49
+ | 3 | Infrastructure failure: a required tool is missing or unusable. |
50
+
51
+ ## License
52
+
53
+ MIT
@@ -0,0 +1,27 @@
1
+ # codeality-py configuration - https://github.com/syntopica/codeality
2
+ schema-version = 1
3
+ source-roots = ["src"]
4
+ test-roots = ["tests"]
5
+ import-package = "codeality_py"
6
+ coverage-threshold = 80
7
+
8
+ [limits]
9
+ max-file-lines = 150
10
+ test-max-file-lines = 300
11
+
12
+ [roles]
13
+ data = [
14
+ "src/codeality_py/traversal/default_excludes.py",
15
+ "src/codeality_py/rules/grab_bag_names.py",
16
+ "src/codeality_py/roles/test_file_patterns.py",
17
+ "src/codeality_py/config/default_generated_globs.py",
18
+ "src/codeality_py/engine/rule_registry.py",
19
+ "src/codeality_py/init/managed_asset_files.py",
20
+ "src/codeality_py/commands/project_option.py",
21
+ ]
22
+ entrypoint = ["src/codeality_py/cli.py"]
23
+
24
+ [[overrides]]
25
+ paths = ["tests/rules/test_no_inline_sql.py", "tests/baseline/test_classify_findings.py"]
26
+ disable = ["BPY006"]
27
+ reason = "Fixtures for the SQL detector and for fingerprinting are queries by definition"
@@ -0,0 +1,10 @@
1
+ ; Managed by codeality-py.
2
+ [mypy]
3
+ strict = True
4
+ warn_unreachable = True
5
+ show_error_codes = True
6
+ pretty = True
7
+ exclude = (?x)(^build/|^dist/|/migrations/)
8
+
9
+ [mypy-tests.*]
10
+ disallow_untyped_defs = False
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27,<2"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "syntopica-codeality-py"
7
+ version = "0.2.0"
8
+ description = "Structural linter and config scaffolder for Python: atomic files, placement, size caps, no inline SQL"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "Cristian Deluxe" }]
13
+ keywords = ["linter", "code-quality", "architecture", "ast"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Topic :: Software Development :: Quality Assurance",
23
+ ]
24
+ dependencies = ["click>=8.1,<9", "tomlkit>=0.13,<1"]
25
+
26
+ [project.scripts]
27
+ codeality-py = "codeality_py.cli:cli"
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/syntopica/codeality"
31
+ Issues = "https://github.com/syntopica/codeality/issues"
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "deptry>=0.20,<1",
36
+ "mypy>=1.11,<2",
37
+ "pip-audit>=2.7,<3",
38
+ "pytest>=8,<10",
39
+ "pytest-cov>=5,<8",
40
+ "ruff>=0.15,<1",
41
+ ]
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = ["src/codeality_py"]
45
+
46
+ [tool.deptry]
47
+ known_first_party = ["codeality_py"]
48
+
49
+ [tool.pytest.ini_options]
50
+ addopts = "-ra"
51
+ testpaths = ["tests"]
52
+
53
+ [tool.coverage.run]
54
+ branch = true
55
+
56
+ [tool.coverage.report]
57
+ show_missing = true
58
+ skip_covered = true
59
+ fail_under = 80
60
+
@@ -0,0 +1,51 @@
1
+ # Managed by codeality-py. Rules are listed explicitly: ALL expands silently on
2
+ # every ruff upgrade, turning a dependency bump into a lint failure.
3
+ line-length = 100
4
+ target-version = "py311"
5
+
6
+ [lint]
7
+ select = [
8
+ "E", # pycodestyle errors
9
+ "W", # pycodestyle warnings
10
+ "F", # pyflakes
11
+ "I", # import sorting
12
+ "N", # pep8-naming
13
+ "UP", # pyupgrade
14
+ "B", # bugbear
15
+ "A", # builtin shadowing
16
+ "C4", # comprehensions
17
+ "DTZ", # naive datetimes
18
+ "T20", # print in library code
19
+ "SIM", # simplifiable code
20
+ "RET", # return control flow
21
+ "ARG", # unused arguments
22
+ "PTH", # pathlib over os.path
23
+ "ERA", # commented-out code
24
+ "PL", # pylint: complexity, branches, statements
25
+ "RUF", # ruff-specific
26
+ "D", # docstrings; replaces interrogate
27
+ # bandit, curated: the full S set is intentionally noisy in tests and in
28
+ # subprocess-heavy code.
29
+ "S102", "S103", "S104", "S105", "S106", "S107", "S108",
30
+ "S301", "S302", "S303", "S304", "S305", "S306",
31
+ "S324", "S501", "S506", "S508", "S509",
32
+ "S608", "S609", "S612",
33
+ ]
34
+ ignore = [
35
+ # Conflicts with the formatter; keeping these on fights ruff format forever.
36
+ "E501", "W191", "E111", "E114", "E117", "D206", "D300", "COM812", "ISC001",
37
+ "D203", # incompatible with D211
38
+ "D107", # an __init__ that stores its arguments has nothing to add to the class docstring
39
+ "D213", # incompatible with D212
40
+ ]
41
+
42
+ [lint.per-file-ignores]
43
+ # **/ so the pattern also reaches nested test roots such as host/tests.
44
+ "**/tests/**" = ["D", "S101", "ARG", "PLR2004"]
45
+ "**/conftest.py" = ["D"]
46
+
47
+ [lint.pydocstyle]
48
+ convention = "google"
49
+
50
+ [format]
51
+ docstring-code-format = true
@@ -0,0 +1 @@
1
+ """Structural linter and config scaffolder for Python projects."""
@@ -0,0 +1,51 @@
1
+ name: Quality
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ gate:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ['3.11', '3.13']
18
+ steps:
19
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
23
+ with:
24
+ enable-cache: true
25
+
26
+ - name: Check the lockfile is current
27
+ run: uv lock --check
28
+
29
+ # Every extra and every group: the gate audits and tests the environment
30
+ # it runs in, and a group-only install leaves out the extras the tests
31
+ # import.
32
+ - name: Install from the lockfile
33
+ run: uv sync --locked --all-extras --all-groups
34
+ env:
35
+ UV_PYTHON: ${{ matrix.python-version }}
36
+
37
+ - name: Run the quality gate
38
+ run: uv run codeality-py gate --json
39
+
40
+ - name: Type-check with pyrefly, without blocking
41
+ continue-on-error: true
42
+ run: |
43
+ uv run --with pyrefly pyrefly check --output-format json > pyrefly.json || true
44
+
45
+ - name: Upload the pyrefly shadow report
46
+ if: always()
47
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
48
+ with:
49
+ name: pyrefly-shadow-${{ matrix.python-version }}
50
+ path: pyrefly.json
51
+ retention-days: 90
@@ -0,0 +1,19 @@
1
+ # codeality-py configuration - https://github.com/syntopica/codeality
2
+ schema-version = 1
3
+ source-roots = ["src"]
4
+ test-roots = ["tests"]
5
+ respect-gitignore = true
6
+ coverage-threshold = 80
7
+
8
+ [limits]
9
+ max-file-lines = 150
10
+ test-max-file-lines = 300
11
+
12
+ # A role states what a file is. Prefer a role over a suppression: it explains
13
+ # the file instead of silencing an alarm.
14
+ [roles]
15
+ data = []
16
+ registry = []
17
+ entrypoint = []
18
+ generated = []
19
+ namespace-init = []
@@ -0,0 +1,12 @@
1
+ ; Managed by codeality-py, scaffolded only with --profile app. Declare the real
2
+ ; layers of the project; an empty contract enforces nothing.
3
+ [importlinter]
4
+ root_package = CHANGE_ME
5
+
6
+ [importlinter:contract:layers]
7
+ name = Layered architecture
8
+ type = layers
9
+ layers =
10
+ cli
11
+ services
12
+ domain