gruff-py 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.
- gruff_py-0.1.0/.editorconfig +20 -0
- gruff_py-0.1.0/.gitattributes +38 -0
- gruff_py-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
- gruff_py-0.1.0/.github/ISSUE_TEMPLATE/false_positive.md +33 -0
- gruff_py-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- gruff_py-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- gruff_py-0.1.0/.github/git-commit-instructions.md +5 -0
- gruff_py-0.1.0/.github/workflows/ci.yml +57 -0
- gruff_py-0.1.0/.github/workflows/publish.yml +60 -0
- gruff_py-0.1.0/.gitignore +88 -0
- gruff_py-0.1.0/.gruff-py.yaml +710 -0
- gruff_py-0.1.0/.pre-commit-config.yaml +27 -0
- gruff_py-0.1.0/CHANGELOG.md +15 -0
- gruff_py-0.1.0/CODE_OF_CONDUCT.md +26 -0
- gruff_py-0.1.0/CONTRIBUTING.md +63 -0
- gruff_py-0.1.0/LICENSE.md +21 -0
- gruff_py-0.1.0/Makefile +64 -0
- gruff_py-0.1.0/PKG-INFO +279 -0
- gruff_py-0.1.0/README.md +242 -0
- gruff_py-0.1.0/SECURITY.md +44 -0
- gruff_py-0.1.0/SUPPORT.md +38 -0
- gruff_py-0.1.0/bin/gruff-py +28 -0
- gruff_py-0.1.0/docs/CONFIGURATION.md +159 -0
- gruff_py-0.1.0/docs/DASHBOARD.md +64 -0
- gruff_py-0.1.0/docs/RELEASING.md +81 -0
- gruff_py-0.1.0/docs/REPORTING.md +144 -0
- gruff_py-0.1.0/docs/RULES.md +1948 -0
- gruff_py-0.1.0/pyproject.toml +138 -0
- gruff_py-0.1.0/scripts/bump-version.sh +253 -0
- gruff_py-0.1.0/scripts/performance-baselines/linux-x86_64.json +16 -0
- gruff_py-0.1.0/scripts/preflight-checks.sh +573 -0
- gruff_py-0.1.0/scripts/publish-pypi.sh +271 -0
- gruff_py-0.1.0/scripts/test-performance.sh +505 -0
- gruff_py-0.1.0/src/gruffpy/__init__.py +5 -0
- gruff_py-0.1.0/src/gruffpy/__main__.py +9 -0
- gruff_py-0.1.0/src/gruffpy/analysis/__init__.py +15 -0
- gruff_py-0.1.0/src/gruffpy/analysis/report.py +163 -0
- gruff_py-0.1.0/src/gruffpy/analysis/run_diagnostic.py +37 -0
- gruff_py-0.1.0/src/gruffpy/analysis/runner.py +286 -0
- gruff_py-0.1.0/src/gruffpy/analysis/schema.py +5 -0
- gruff_py-0.1.0/src/gruffpy/cli.py +741 -0
- gruff_py-0.1.0/src/gruffpy/cli_menu.py +131 -0
- gruff_py-0.1.0/src/gruffpy/cli_options.py +769 -0
- gruff_py-0.1.0/src/gruffpy/cli_state.py +54 -0
- gruff_py-0.1.0/src/gruffpy/command/__init__.py +4 -0
- gruff_py-0.1.0/src/gruffpy/command/dashboard_page_renderer.py +229 -0
- gruff_py-0.1.0/src/gruffpy/command/dashboard_server.py +282 -0
- gruff_py-0.1.0/src/gruffpy/command/metric_calibration.py +723 -0
- gruff_py-0.1.0/src/gruffpy/command/rule_docs.py +322 -0
- gruff_py-0.1.0/src/gruffpy/config/__init__.py +13 -0
- gruff_py-0.1.0/src/gruffpy/config/analysis_config.py +182 -0
- gruff_py-0.1.0/src/gruffpy/config/dead_code_allowlist.py +66 -0
- gruff_py-0.1.0/src/gruffpy/config/exceptions.py +5 -0
- gruff_py-0.1.0/src/gruffpy/config/loader.py +382 -0
- gruff_py-0.1.0/src/gruffpy/config/rule_selection.py +69 -0
- gruff_py-0.1.0/src/gruffpy/config/rule_settings.py +180 -0
- gruff_py-0.1.0/src/gruffpy/config/yaml_loader.py +41 -0
- gruff_py-0.1.0/src/gruffpy/finding/__init__.py +19 -0
- gruff_py-0.1.0/src/gruffpy/finding/confidence.py +9 -0
- gruff_py-0.1.0/src/gruffpy/finding/fail_threshold.py +50 -0
- gruff_py-0.1.0/src/gruffpy/finding/finding.py +98 -0
- gruff_py-0.1.0/src/gruffpy/finding/fingerprint.py +48 -0
- gruff_py-0.1.0/src/gruffpy/finding/output_format.py +31 -0
- gruff_py-0.1.0/src/gruffpy/finding/pillar.py +20 -0
- gruff_py-0.1.0/src/gruffpy/finding/rule_tier.py +7 -0
- gruff_py-0.1.0/src/gruffpy/finding/severity.py +27 -0
- gruff_py-0.1.0/src/gruffpy/parser/__init__.py +4 -0
- gruff_py-0.1.0/src/gruffpy/parser/analysis_unit.py +49 -0
- gruff_py-0.1.0/src/gruffpy/parser/python_parser.py +61 -0
- gruff_py-0.1.0/src/gruffpy/py.typed +0 -0
- gruff_py-0.1.0/src/gruffpy/reporting/__init__.py +19 -0
- gruff_py-0.1.0/src/gruffpy/reporting/finding_display_filter.py +103 -0
- gruff_py-0.1.0/src/gruffpy/reporting/github_annotations_reporter.py +55 -0
- gruff_py-0.1.0/src/gruffpy/reporting/hotspot_reporter.py +36 -0
- gruff_py-0.1.0/src/gruffpy/reporting/html_reporter.py +442 -0
- gruff_py-0.1.0/src/gruffpy/reporting/json_reporter.py +41 -0
- gruff_py-0.1.0/src/gruffpy/reporting/markdown_reporter.py +108 -0
- gruff_py-0.1.0/src/gruffpy/reporting/sarif_reporter.py +184 -0
- gruff_py-0.1.0/src/gruffpy/reporting/text_reporter.py +115 -0
- gruff_py-0.1.0/src/gruffpy/rule/__init__.py +6 -0
- gruff_py-0.1.0/src/gruffpy/rule/_python_dynamism.py +309 -0
- gruff_py-0.1.0/src/gruffpy/rule/builtins.py +11 -0
- gruff_py-0.1.0/src/gruffpy/rule/catalog.py +574 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/_halstead.py +213 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/_walks.py +88 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/cognitive_complexity_rule.py +310 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/cyclomatic_complexity_rule.py +159 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/halstead_volume_rule.py +106 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/maintainability_index_rule.py +133 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/nesting_depth_rule.py +191 -0
- gruff_py-0.1.0/src/gruffpy/rule/complexity/npath_complexity_rule.py +248 -0
- gruff_py-0.1.0/src/gruffpy/rule/context.py +34 -0
- gruff_py-0.1.0/src/gruffpy/rule/dead_code/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/dead_code/unused_private_attribute_rule.py +209 -0
- gruff_py-0.1.0/src/gruffpy/rule/dead_code/unused_private_function_rule.py +300 -0
- gruff_py-0.1.0/src/gruffpy/rule/definition.py +70 -0
- gruff_py-0.1.0/src/gruffpy/rule/design/__init__.py +3 -0
- gruff_py-0.1.0/src/gruffpy/rule/design/single_implementor_protocol_rule.py +454 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/_comment_scanner.py +50 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/_docstring_parser.py +138 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/_helpers.py +182 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/complex_branch_rationale_rule.py +227 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/dataclass_attributes_rule.py +270 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/ignore_directive_reason_rule.py +173 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_class_docstring_rule.py +115 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_function_docstring_rule.py +158 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_module_docstring_rule.py +105 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_param_doc_rule.py +191 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_raises_doc_rule.py +126 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_readme_rule.py +86 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/missing_return_doc_rule.py +129 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/stale_param_doc_rule.py +136 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/todo_density_rule.py +108 -0
- gruff_py-0.1.0/src/gruffpy/rule/docs/useless_docstring_rule.py +298 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/_allowlists.py +23 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/_identifier_tokenizer.py +64 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/abbreviation_rule.py +205 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/boolean_prefix_rule.py +315 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/confusing_name_rule.py +109 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/generic_function_rule.py +116 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/hungarian_notation_rule.py +200 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/identifier_quality_rule.py +181 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/module_name_mismatch_rule.py +267 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/parameter_type_name_rule.py +393 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/short_variable_rule.py +178 -0
- gruff_py-0.1.0/src/gruffpy/rule/naming/test_naming_consistency_rule.py +142 -0
- gruff_py-0.1.0/src/gruffpy/rule/project_rule.py +19 -0
- gruff_py-0.1.0/src/gruffpy/rule/registry.py +198 -0
- gruff_py-0.1.0/src/gruffpy/rule/rule.py +21 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/_security_metadata.py +127 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/_security_node_helper.py +265 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/_security_taint_helper.py +376 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/cors_wildcard_with_credentials_rule.py +156 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/dangerous_function_call_rule.py +122 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/disabled_ssl_verification_rule.py +383 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/django_mark_safe_rule.py +161 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/django_raw_sql_rule.py +139 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/error_suppression_rule.py +134 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/extract_compact_user_input_rule.py +121 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/flask_debug_enabled_rule.py +175 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/hardcoded_bind_all_interfaces_rule.py +172 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/hardcoded_framework_secret_key_rule.py +149 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/header_injection_rule.py +114 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/insecure_random_rule.py +132 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/insecure_temp_file_rule.py +186 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/insecure_tls_protocol_rule.py +132 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/jinja2_autoescape_off_rule.py +185 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/paramiko_no_host_key_check_rule.py +175 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/path_traversal_rule.py +191 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/shell_injection_rule.py +137 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/silent_except_rule.py +109 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/sql_concatenation_rule.py +160 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/ssrf_rule.py +172 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/unsafe_pickle_rule.py +166 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/unsafe_yaml_load_rule.py +355 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/variable_import_rule.py +103 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/weak_crypto_rule.py +260 -0
- gruff_py-0.1.0/src/gruffpy/rule/security/xxe_rule.py +231 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/_secret_scanner_helper.py +138 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/api_key_pattern_rule.py +108 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/aws_access_key_rule.py +90 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/database_url_password_rule.py +137 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/hardcoded_env_value_rule.py +120 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/high_entropy_string_rule.py +120 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/jwt_token_rule.py +80 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/phi_pattern_rule.py +103 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/pii_test_fixture_rule.py +132 -0
- gruff_py-0.1.0/src/gruffpy/rule/sensitive_data/private_key_rule.py +86 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/__init__.py +3 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/_lines.py +89 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/attribute_count_rule.py +172 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/average_function_length_rule.py +150 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/class_length_rule.py +129 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/file_length_rule.py +88 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/function_length_rule.py +135 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/parameter_count_rule.py +128 -0
- gruff_py-0.1.0/src/gruffpy/rule/size/public_method_count_rule.py +134 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/_pytest_config.py +159 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/_test_quality_node_helper.py +359 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/_test_quality_scope.py +33 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/conditional_logic_rule.py +97 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/eager_test_rule.py +104 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/empty_parametrize_rule.py +99 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/exception_type_only_rule.py +124 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/excessive_mocking_rule.py +98 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/extends_production_class_rule.py +149 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/global_state_mutation_rule.py +95 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/loop_assertion_without_message_rule.py +102 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/loop_in_test_rule.py +98 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/magic_number_assertion_rule.py +317 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/mock_only_test_rule.py +120 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/mock_without_expectation_rule.py +125 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/mocking_domain_object_rule.py +136 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/multiple_aaa_cycles_rule.py +129 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/mystery_guest_rule.py +121 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/naming_consistency_rule.py +103 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/no_assertions_rule.py +107 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/parametrize_annotation_rule.py +142 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/private_reflection_rule.py +107 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/pytest_coverage_source_missing_rule.py +86 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/pytest_deprecations_not_fatal_rule.py +85 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/pytest_strict_config_missing_rule.py +93 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/repeated_structure_missing_parametrize_rule.py +133 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/setup_bloat_rule.py +114 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/skipped_without_reason_rule.py +156 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/sleep_in_test_rule.py +98 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/sut_not_called_rule.py +273 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/tautological_type_assertion_rule.py +140 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/test_function_too_long_rule.py +105 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/test_longer_than_sut_rule.py +130 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/testdox_readability_rule.py +100 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/trivial_assertion_rule.py +104 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/trivial_snapshot_rule.py +113 -0
- gruff_py-0.1.0/src/gruffpy/rule/test_quality/unused_mock_rule.py +109 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/__init__.py +0 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/commented_out_code_rule.py +155 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/empty_class_rule.py +152 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/empty_function_rule.py +123 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/one_line_function_rule.py +166 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/redundant_variable_rule.py +151 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/unreachable_code_rule.py +231 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/unused_import_rule.py +208 -0
- gruff_py-0.1.0/src/gruffpy/rule/waste/unused_parameter_rule.py +211 -0
- gruff_py-0.1.0/src/gruffpy/scoring/__init__.py +25 -0
- gruff_py-0.1.0/src/gruffpy/scoring/composite_finding_factory.py +151 -0
- gruff_py-0.1.0/src/gruffpy/scoring/file_score.py +60 -0
- gruff_py-0.1.0/src/gruffpy/scoring/grade.py +52 -0
- gruff_py-0.1.0/src/gruffpy/scoring/pillar_score.py +52 -0
- gruff_py-0.1.0/src/gruffpy/scoring/score_calculator.py +196 -0
- gruff_py-0.1.0/src/gruffpy/scoring/score_report.py +48 -0
- gruff_py-0.1.0/src/gruffpy/source/__init__.py +20 -0
- gruff_py-0.1.0/src/gruffpy/source/discovery.py +343 -0
- gruff_py-0.1.0/src/gruffpy/source/gitignore.py +170 -0
- gruff_py-0.1.0/src/gruffpy/source/source_file.py +32 -0
- gruff_py-0.1.0/src/gruffpy/suppression/__init__.py +11 -0
- gruff_py-0.1.0/src/gruffpy/suppression/filter.py +37 -0
- gruff_py-0.1.0/src/gruffpy/suppression/parser.py +273 -0
- gruff_py-0.1.0/src/gruffpy/version.py +4 -0
- gruff_py-0.1.0/tests/__init__.py +0 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.complex-branch-rationale/negative/docstring_rationale.py +30 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.complex-branch-rationale/positive/no_rationale.py +25 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.dataclass-attributes/negative/attributes_section.py +16 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.dataclass-attributes/positive/missing_attrs.py +8 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.ignore-directive-reason/negative/reexport_reason.py +3 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.ignore-directive-reason/positive/unexplained.py +3 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.todo-density/negative/src/gruffpy/rule/docs/todo_density_rule.py +11 -0
- gruff_py-0.1.0/tests/fixtures/calibration/docs.todo-density/positive/high_density.py +9 -0
- gruff_py-0.1.0/tests/fixtures/complexity/cc_fixture.py +76 -0
- gruff_py-0.1.0/tests/fixtures/complexity/radon_ground_truth.md +47 -0
- gruff_py-0.1.0/tests/integration/__init__.py +0 -0
- gruff_py-0.1.0/tests/integration/test_bin_script.py +19 -0
- gruff_py-0.1.0/tests/integration/test_cli_smoke.py +490 -0
- gruff_py-0.1.0/tests/integration/test_dashboard_server.py +85 -0
- gruff_py-0.1.0/tests/integration/test_gitignore_e2e.py +78 -0
- gruff_py-0.1.0/tests/integration/test_json_byte_equivalence.py +75 -0
- gruff_py-0.1.0/tests/integration/test_perf_script_smoke.py +189 -0
- gruff_py-0.1.0/tests/integration/test_suppression.py +140 -0
- gruff_py-0.1.0/tests/unit/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/command/__init__.py +1 -0
- gruff_py-0.1.0/tests/unit/command/test_dashboard_page_renderer.py +110 -0
- gruff_py-0.1.0/tests/unit/command/test_metric_calibration.py +121 -0
- gruff_py-0.1.0/tests/unit/command/test_rule_docs.py +31 -0
- gruff_py-0.1.0/tests/unit/config/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/config/test_dead_code_allowlist_loader.py +91 -0
- gruff_py-0.1.0/tests/unit/config/test_gruff_py_yaml_registry_coverage.py +118 -0
- gruff_py-0.1.0/tests/unit/config/test_loader_precedence.py +336 -0
- gruff_py-0.1.0/tests/unit/config/test_yaml_loader.py +71 -0
- gruff_py-0.1.0/tests/unit/finding/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/finding/test_fingerprint.py +80 -0
- gruff_py-0.1.0/tests/unit/parser/test_python_parser.py +42 -0
- gruff_py-0.1.0/tests/unit/reporting/__init__.py +1 -0
- gruff_py-0.1.0/tests/unit/reporting/test_reporters.py +426 -0
- gruff_py-0.1.0/tests/unit/rule/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_cognitive_complexity_rule.py +192 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_complexity_pillar_integration.py +289 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_cyclomatic_complexity_rule.py +133 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_halstead_volume_rule.py +165 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_maintainability_index_rule.py +132 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_nesting_depth_rule.py +136 -0
- gruff_py-0.1.0/tests/unit/rule/complexity/test_npath_complexity_rule.py +126 -0
- gruff_py-0.1.0/tests/unit/rule/dead_code/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/dead_code/test_dead_code_allowlist.py +158 -0
- gruff_py-0.1.0/tests/unit/rule/dead_code/test_unused_private_attribute_rule.py +102 -0
- gruff_py-0.1.0/tests/unit/rule/dead_code/test_unused_private_function_rule.py +120 -0
- gruff_py-0.1.0/tests/unit/rule/design/__init__.py +1 -0
- gruff_py-0.1.0/tests/unit/rule/design/test_single_implementor_protocol_rule.py +88 -0
- gruff_py-0.1.0/tests/unit/rule/docs/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/docs/_helpers.py +52 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_complex_branch_rationale_rule.py +81 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_dataclass_attributes_rule.py +133 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_docs_pillar_integration.py +179 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_docstring_parser.py +218 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_ignore_directive_reason_rule.py +49 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_class_docstring_rule.py +55 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_function_docstring_rule.py +132 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_module_docstring_rule.py +44 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_param_doc_rule.py +70 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_raises_doc_rule.py +56 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_readme_rule.py +44 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_missing_return_doc_rule.py +36 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_stale_param_doc_rule.py +68 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_todo_density_rule.py +71 -0
- gruff_py-0.1.0/tests/unit/rule/docs/test_useless_docstring_rule.py +89 -0
- gruff_py-0.1.0/tests/unit/rule/naming/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_abbreviation_rule.py +106 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_boolean_prefix_rule.py +228 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_confusing_name_rule.py +80 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_generic_function_rule.py +87 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_hungarian_notation_rule.py +136 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_identifier_quality_rule.py +111 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_identifier_tokenizer.py +62 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_module_name_mismatch_rule.py +133 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_naming_pillar_integration.py +156 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_parameter_type_name_rule.py +222 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_short_variable_rule.py +100 -0
- gruff_py-0.1.0/tests/unit/rule/naming/test_test_naming_consistency_rule.py +74 -0
- gruff_py-0.1.0/tests/unit/rule/security/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/security/_helpers.py +44 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_cors_wildcard_with_credentials_rule.py +72 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_dangerous_function_call_rule.py +38 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_disabled_ssl_verification_rule.py +71 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_django_mark_safe_rule.py +102 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_django_raw_sql_rule.py +97 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_error_suppression_rule.py +24 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_extract_compact_user_input_rule.py +30 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_flask_debug_enabled_rule.py +78 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_hardcoded_bind_all_interfaces_rule.py +70 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_hardcoded_framework_secret_key_rule.py +68 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_header_injection_rule.py +34 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_insecure_random_rule.py +24 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_insecure_temp_file_rule.py +73 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_insecure_tls_protocol_rule.py +63 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_jinja2_autoescape_off_rule.py +71 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_paramiko_no_host_key_check_rule.py +74 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_path_traversal_rule.py +134 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_security_pillar_integration.py +150 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_security_taint_helper.py +224 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_shell_injection_rule.py +29 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_silent_except_rule.py +35 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_sql_concatenation_rule.py +58 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_ssrf_rule.py +146 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_unsafe_pickle_rule.py +75 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_unsafe_yaml_load_rule.py +92 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_variable_import_rule.py +19 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_weak_crypto_rule.py +48 -0
- gruff_py-0.1.0/tests/unit/rule/security/test_xxe_rule.py +86 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/_helpers.py +49 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_api_key_pattern_rule.py +40 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_aws_access_key_rule.py +49 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_database_url_password_rule.py +29 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_hardcoded_env_value_rule.py +31 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_high_entropy_string_rule.py +31 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_jwt_token_rule.py +25 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_phi_pattern_rule.py +28 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_pii_test_fixture_rule.py +43 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_private_key_rule.py +30 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_secret_scanner_helper.py +46 -0
- gruff_py-0.1.0/tests/unit/rule/sensitive_data/test_sensitive_data_pillar_integration.py +100 -0
- gruff_py-0.1.0/tests/unit/rule/size/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_attribute_count_rule.py +121 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_average_function_length_rule.py +83 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_class_length_rule.py +81 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_file_length_rule.py +84 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_function_length_rule.py +139 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_lines_helper.py +101 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_parameter_count_rule.py +108 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_public_method_count_rule.py +91 -0
- gruff_py-0.1.0/tests/unit/rule/size/test_size_pillar_integration.py +362 -0
- gruff_py-0.1.0/tests/unit/rule/test_calibration_fixtures.py +87 -0
- gruff_py-0.1.0/tests/unit/rule/test_catalog.py +155 -0
- gruff_py-0.1.0/tests/unit/rule/test_python_dynamism.py +145 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/_helpers.py +45 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_conditional_logic_rule.py +25 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_empty_parametrize_rule.py +18 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_extends_production_class_rule.py +37 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_full_pillar_integration.py +324 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_global_state_mutation_rule.py +13 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_loop_in_test_rule.py +25 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_magic_number_assertion_rule.py +89 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_memoisation_gate.py +56 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_mock_lifecycle_integration.py +96 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_naming_consistency_rule.py +19 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_no_assertions_rule.py +33 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_private_reflection_rule.py +19 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_project_config_rules.py +191 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_repeated_structure_missing_parametrize_rule.py +96 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_skipped_without_reason_rule.py +29 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_sleep_in_test_rule.py +24 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_sut_not_called_rule.py +94 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_tautological_type_assertion_rule.py +23 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_test_function_too_long_rule.py +59 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_trivial_assertion_rule.py +31 -0
- gruff_py-0.1.0/tests/unit/rule/test_quality/test_unused_mock_rule.py +35 -0
- gruff_py-0.1.0/tests/unit/rule/test_threshold_contract.py +138 -0
- gruff_py-0.1.0/tests/unit/rule/waste/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_commented_out_code_rule.py +96 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_dead_code_waste_pillar_integration.py +148 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_empty_class_and_function.py +163 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_one_line_function_rule.py +95 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_redundant_variable_rule.py +96 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_unreachable_code_rule.py +222 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_unused_import_rule.py +154 -0
- gruff_py-0.1.0/tests/unit/rule/waste/test_unused_parameter_rule.py +128 -0
- gruff_py-0.1.0/tests/unit/scoring/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/scoring/test_composite_finding_factory.py +146 -0
- gruff_py-0.1.0/tests/unit/scoring/test_score_calculator.py +43 -0
- gruff_py-0.1.0/tests/unit/source/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/source/test_discovery_gitignore.py +145 -0
- gruff_py-0.1.0/tests/unit/source/test_gitignore_contract.py +135 -0
- gruff_py-0.1.0/tests/unit/source/test_gitignore_matcher.py +176 -0
- gruff_py-0.1.0/tests/unit/suppression/__init__.py +0 -0
- gruff_py-0.1.0/tests/unit/suppression/test_filter.py +74 -0
- gruff_py-0.1.0/tests/unit/suppression/test_parser.py +71 -0
- gruff_py-0.1.0/uv.lock +499 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
end_of_line = lf
|
|
5
|
+
indent_style = space
|
|
6
|
+
indent_size = 4
|
|
7
|
+
charset = utf-8
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
|
|
11
|
+
[*.py]
|
|
12
|
+
indent_style = space
|
|
13
|
+
indent_size = 4
|
|
14
|
+
max_line_length = 100
|
|
15
|
+
|
|
16
|
+
[*.{md,toml,yaml,yml,json}]
|
|
17
|
+
indent_size = 2
|
|
18
|
+
|
|
19
|
+
[Makefile]
|
|
20
|
+
indent_style = tab
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Normalize text files to LF on commit; let git decide what's text.
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Per-extension overrides (explicit > auto for source/config).
|
|
5
|
+
*.py text eol=lf
|
|
6
|
+
*.pyi text eol=lf
|
|
7
|
+
*.sh text eol=lf
|
|
8
|
+
*.yml text eol=lf
|
|
9
|
+
*.yaml text eol=lf
|
|
10
|
+
*.md text eol=lf
|
|
11
|
+
*.ini text eol=lf
|
|
12
|
+
*.toml text eol=lf
|
|
13
|
+
*.cfg text eol=lf
|
|
14
|
+
*.json text eol=lf
|
|
15
|
+
.editorconfig text eol=lf
|
|
16
|
+
|
|
17
|
+
# Windows-only files: keep CRLF.
|
|
18
|
+
*.bat text eol=crlf
|
|
19
|
+
*.cmd text eol=crlf
|
|
20
|
+
*.ps1 text eol=crlf
|
|
21
|
+
|
|
22
|
+
# Binary files — don't normalize, don't diff.
|
|
23
|
+
*.png binary
|
|
24
|
+
*.jpg binary
|
|
25
|
+
*.jpeg binary
|
|
26
|
+
*.gif binary
|
|
27
|
+
*.ico binary
|
|
28
|
+
*.pdf binary
|
|
29
|
+
*.whl binary
|
|
30
|
+
*.zip binary
|
|
31
|
+
*.gz binary
|
|
32
|
+
*.tar binary
|
|
33
|
+
*.tar.gz binary
|
|
34
|
+
*.7z binary
|
|
35
|
+
*.exe binary
|
|
36
|
+
*.dll binary
|
|
37
|
+
*.so binary
|
|
38
|
+
*.dylib binary
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report incorrect behaviour in gruff-py
|
|
4
|
+
title: ""
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Version
|
|
10
|
+
|
|
11
|
+
- gruff-py:
|
|
12
|
+
- Python:
|
|
13
|
+
- OS:
|
|
14
|
+
|
|
15
|
+
## Command
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Expected Behaviour
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Actual Behaviour
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Minimal Reproduction
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: False positive
|
|
3
|
+
about: Report a finding that should not be emitted
|
|
4
|
+
title: ""
|
|
5
|
+
labels: false-positive
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Rule
|
|
10
|
+
|
|
11
|
+
Rule id:
|
|
12
|
+
|
|
13
|
+
## Version
|
|
14
|
+
|
|
15
|
+
- gruff-py:
|
|
16
|
+
- Python:
|
|
17
|
+
- OS:
|
|
18
|
+
|
|
19
|
+
## Code Sample
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Finding
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Why This Should Be Allowed
|
|
32
|
+
|
|
33
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest a rule, reporter, config option, or workflow
|
|
4
|
+
title: ""
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## Proposed Behaviour
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Alternatives Considered
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Compatibility Notes
|
|
19
|
+
|
|
20
|
+
Does this change any schema fields, rule ids, fingerprints, exit-code behaviour,
|
|
21
|
+
or report format names?
|
|
22
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
-
|
|
4
|
+
|
|
5
|
+
## Verification
|
|
6
|
+
|
|
7
|
+
- [ ] `uv run ruff check src tests`
|
|
8
|
+
- [ ] `uv run ruff format --check src tests`
|
|
9
|
+
- [ ] `uv run mypy src`
|
|
10
|
+
- [ ] `uv run pytest`
|
|
11
|
+
|
|
12
|
+
## Compatibility Checklist
|
|
13
|
+
|
|
14
|
+
- [ ] No unintended schema string changes
|
|
15
|
+
- [ ] No unintended fingerprint changes
|
|
16
|
+
- [ ] No unintended public rule id changes
|
|
17
|
+
- [ ] Docs updated where behaviour changed
|
|
18
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Git Commit Instructions
|
|
2
|
+
|
|
3
|
+
Use concise conventional commits when practical, for example `feat: add size rule` or `fix: preserve fingerprint compatibility`.
|
|
4
|
+
|
|
5
|
+
Keep commits focused by boundary: runtime code with its tests, GOAT Flow setup docs, and generated package artifacts should not be mixed unless the user explicitly asks for a single combined commit. Do not commit `node_modules/`, `dist/`, `.venv/`, or local cache directories.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
check:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v3
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
run: uv python install ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install project
|
|
28
|
+
run: uv sync --all-extras --dev --python ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Bash syntax
|
|
31
|
+
run: bash -n scripts/*.sh
|
|
32
|
+
|
|
33
|
+
- name: Shellcheck
|
|
34
|
+
uses: ludeeus/action-shellcheck@master
|
|
35
|
+
with:
|
|
36
|
+
scandir: ./scripts
|
|
37
|
+
|
|
38
|
+
- name: Lint
|
|
39
|
+
run: uv run ruff check src tests
|
|
40
|
+
|
|
41
|
+
- name: Format check
|
|
42
|
+
run: uv run ruff format --check src tests
|
|
43
|
+
|
|
44
|
+
- name: Typecheck
|
|
45
|
+
run: uv run mypy src
|
|
46
|
+
|
|
47
|
+
- name: Rule docs
|
|
48
|
+
run: uv run python -m gruffpy.command.rule_docs --check docs/RULES.md
|
|
49
|
+
|
|
50
|
+
- name: Test
|
|
51
|
+
run: uv run pytest
|
|
52
|
+
|
|
53
|
+
- name: Gruff self-check
|
|
54
|
+
run: uv run gruff-py analyse src tests --fail-on advisory
|
|
55
|
+
|
|
56
|
+
- name: Package build
|
|
57
|
+
run: uv build
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
name: Build and publish to PyPI
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment:
|
|
15
|
+
name: pypi
|
|
16
|
+
url: https://pypi.org/project/gruff-py/
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v3
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install 3.11
|
|
31
|
+
|
|
32
|
+
- name: Install project
|
|
33
|
+
run: uv sync --all-extras --dev --python 3.11
|
|
34
|
+
|
|
35
|
+
- name: Verify tag matches project version
|
|
36
|
+
run: |
|
|
37
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
38
|
+
pyver=$(uv run python -c 'import tomllib, pathlib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')
|
|
39
|
+
if [[ "$tag" != "$pyver" ]]; then
|
|
40
|
+
echo "::error::Tag '${GITHUB_REF_NAME}' does not match pyproject.toml version '$pyver'"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
- name: Lint
|
|
45
|
+
run: uv run ruff check src tests
|
|
46
|
+
|
|
47
|
+
- name: Format check
|
|
48
|
+
run: uv run ruff format --check src tests
|
|
49
|
+
|
|
50
|
+
- name: Typecheck
|
|
51
|
+
run: uv run mypy src
|
|
52
|
+
|
|
53
|
+
- name: Test
|
|
54
|
+
run: uv run pytest
|
|
55
|
+
|
|
56
|
+
- name: Build sdist and wheel
|
|
57
|
+
run: uv build
|
|
58
|
+
|
|
59
|
+
- name: Publish to PyPI
|
|
60
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ----- Build artifacts -----
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
*.whl
|
|
7
|
+
|
|
8
|
+
# ----- Python bytecode and shared objects -----
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
*.so
|
|
13
|
+
*.pyd
|
|
14
|
+
|
|
15
|
+
# ----- Virtual environments -----
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
ENV/
|
|
20
|
+
__pypackages__/
|
|
21
|
+
|
|
22
|
+
# ----- Local config and secrets (dotenv-style files) -----
|
|
23
|
+
# (Note: NOT a virtualenv. `.env` is almost always a KEY=value file with secrets.)
|
|
24
|
+
.env
|
|
25
|
+
.env.local
|
|
26
|
+
.env.*.local
|
|
27
|
+
.envrc.local
|
|
28
|
+
|
|
29
|
+
# ----- Coverage and test caches -----
|
|
30
|
+
htmlcov/
|
|
31
|
+
.tox/
|
|
32
|
+
.nox/
|
|
33
|
+
.coverage
|
|
34
|
+
.coverage.*
|
|
35
|
+
.pytest_cache/
|
|
36
|
+
.hypothesis/
|
|
37
|
+
coverage.xml
|
|
38
|
+
*.cover
|
|
39
|
+
|
|
40
|
+
# ----- Type checker / linter / formatter caches -----
|
|
41
|
+
.mypy_cache/
|
|
42
|
+
.dmypy.json
|
|
43
|
+
dmypy.json
|
|
44
|
+
.pyre/
|
|
45
|
+
.pytype/
|
|
46
|
+
.ruff_cache/
|
|
47
|
+
cython_debug/
|
|
48
|
+
|
|
49
|
+
# ----- Publishing -----
|
|
50
|
+
.pypirc
|
|
51
|
+
|
|
52
|
+
# ----- Logs and pip artifacts -----
|
|
53
|
+
*.log
|
|
54
|
+
pip-log.txt
|
|
55
|
+
pip-delete-this-directory.txt
|
|
56
|
+
|
|
57
|
+
# ----- IDE / editor -----
|
|
58
|
+
.idea/
|
|
59
|
+
.vscode/
|
|
60
|
+
.spyderproject
|
|
61
|
+
.spyproject
|
|
62
|
+
.ropeproject
|
|
63
|
+
*.swp
|
|
64
|
+
*.swo
|
|
65
|
+
.*.swp
|
|
66
|
+
.*.swo
|
|
67
|
+
*~
|
|
68
|
+
*.bak
|
|
69
|
+
|
|
70
|
+
# ----- OS files -----
|
|
71
|
+
.DS_Store
|
|
72
|
+
Thumbs.db
|
|
73
|
+
|
|
74
|
+
# ----- Performance harness output -----
|
|
75
|
+
perf-out/
|
|
76
|
+
|
|
77
|
+
# ----- Claude Code (per-user overrides; shared .claude/settings.json stays tracked) -----
|
|
78
|
+
.claude/settings.local.json
|
|
79
|
+
|
|
80
|
+
# ----- Codex (per-user overrides; shared .codex/config.toml stays tracked) -----
|
|
81
|
+
.codex/config.local.toml
|
|
82
|
+
|
|
83
|
+
/node_modules
|
|
84
|
+
|
|
85
|
+
# ----- Not ignored on purpose (keep tracked) -----
|
|
86
|
+
# uv.lock → committed: gruff is a CLI app; lock = reproducible installs.
|
|
87
|
+
# gruff-baseline.json, .gruff-history.json → committed: project-level state.
|
|
88
|
+
# .python-version → if present, used for team Python pinning.
|