mirror of
https://github.com/apache/superset.git
synced 2026-05-24 01:05:21 +00:00
Follow-up to #40231 (merged), where a reviewer flagged a function-body `from datetime import datetime, timedelta` instead of a top-of-file import. Adds a `ruff-import-placement` pre-commit hook running `ruff check --select PLC0415 --preview --no-fix`. Per @rusackas's pushback on the first cut of this PR — which spammed 2,657 `# noqa: PLC0415` annotations across ~410 files without fixing anything — this revision is a much smaller surface area: 1. **Per-file-ignores** for whole directories where function-body imports are a deliberate pattern, not an oversight: - `superset/cli/**` and `scripts/**`: subcommand-deferred imports keep heavy modules out of the CLI startup path. - `superset/tasks/**`: Celery task bodies defer imports of the modules they orchestrate. - `superset/migrations/versions/**`: Alembic migrations interact with model state at runtime, not at module load. - `superset/mcp_service/**`: MCP tools lazy-load resources on invocation so the server can register many tools without paying their import cost at startup. - `superset/db_engine_specs/**`: engine specs defer driver imports so optional DB drivers don't have to be installed. - `superset/initialization/__init__.py`, `superset/extensions/__init__.py`, `superset/app.py`: the app-factory and extension wiring are intentionally full of circular-import workarounds. - `tests/**`: test files routinely defer imports for fixture isolation; the rule still applies to production code. 2. **Per-line `# noqa: PLC0415`** on the 259 remaining genuine circular-import sites (security/manager.py, sql/execution/executor.py, semantic_layers/labels.py, tags/core.py, core_api_injection.py, etc.). These are foundational modules where moving the imports up would actually break things. Net result: ~410 files / 2,657 grandfathered → ~73 files / 259 actual noqa annotations. The rule still catches every new function-body import outside the explicitly-allowed directories. Also: silences a pre-existing C901 on `mcp_service/sql_lab/tool/execute_sql.py` that fires under newer local ruff but not CI's pinned ruff 0.9.7 — blocks the local pre-commit run otherwise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Superset CLI Tests
This directory contains tests for the superset-extensions-cli package, focusing on the init command and other CLI functionality.
Test Structure
Core Test Files
test_cli_init.py: Comprehensive tests for theinitcommand scaffoldertest_templates.py: Unit tests for Jinja2 template renderingconftest.py: Pytest fixtures and configurationutils.py: Reusable testing utilities and helpers
Test Categories
Unit Tests (@pytest.mark.unit)
- Template rendering functionality
- Individual function testing
- Input validation logic
Integration Tests (@pytest.mark.integration)
- Complete CLI command workflows
- End-to-end scaffolding processes
CLI Tests (@pytest.mark.cli)
- Click command interface testing
- User input simulation
- Command output verification
Testing Approach for Scaffolders/Generators
The tests use these patterns for testing code generators:
1. Isolated Environment Testing
@pytest.fixture
def isolated_filesystem(tmp_path):
"""Provide isolated temporary directory for each test."""
2. Click CLI Testing Framework
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(app, ["init"], input="...")
3. File Structure Validation
from tests.utils import assert_file_structure, assert_directory_structure
assert_file_structure(extension_path, expected_files)
4. Template Content Verification
from tests.utils import assert_json_content
assert_json_content(json_path, {"name": "expected_value"})
5. Parametrized Testing
@pytest.mark.parametrize("include_frontend,include_backend", [
(True, True), (True, False), (False, True), (False, False)
])
Key Test Cases
Init Command Tests
- ✅ Creates extension with both frontend and backend
- ✅ Creates frontend-only extensions
- ✅ Creates backend-only extensions
- ✅ Validates extension naming (alphanumeric + underscore only)
- ✅ Handles existing directory conflicts
- ✅ Verifies generated file content accuracy
- ✅ Tests custom version and license inputs
- ✅ Integration test for complete workflow
Template Rendering Tests
- ✅ Extension.json template with various configurations
- ✅ Package.json template rendering
- ✅ Pyproject.toml template rendering
- ✅ Template validation with different names/versions/licenses
- ✅ JSON validity verification
- ✅ Whitespace and formatting checks
Running Tests
All tests
pytest
Specific test categories
pytest -m unit # Unit tests only
pytest -m integration # Integration tests only
pytest -m cli # CLI tests only
With coverage
pytest --cov=superset_extensions_cli --cov-report=html
Specific test files
pytest tests/test_cli_init.py
pytest tests/test_templates.py
Reusable Testing Infrastructure
The testing infrastructure is designed for reusability:
Test Utilities (tests/utils.py)
assert_file_exists()/assert_directory_exists()assert_file_structure()/assert_directory_structure()assert_json_content()/load_json_file()create_test_extension_structure()- Helper for expected structures
Fixtures (tests/conftest.py)
cli_runner- Click CLI runnerisolated_filesystem- Temporary directory with cleanupextension_params- Default extension parameterscli_input_*- Pre-configured user inputs
This infrastructure can be easily extended for testing additional CLI commands like build, bundle, dev, and validate.
Best Practices Implemented
- Isolation: Each test runs in its own temporary directory
- Comprehensive Coverage: Tests cover happy paths, edge cases, and error conditions
- Realistic Testing: Uses actual Click CLI runner with realistic user input
- Content Verification: Validates both file existence and content accuracy
- Template Testing: Separates template rendering logic from CLI integration
- Reusable Components: Utilities and fixtures designed for extension
- Clear Documentation: Well-documented test cases and helper functions
- Type Safety: Uses modern Python type annotations with
from __future__ import annotations