diff --git a/py_pglite/__init__.py b/py_pglite/__init__.py index 1d1a1f3..900ff54 100644 --- a/py_pglite/__init__.py +++ b/py_pglite/__init__.py @@ -4,7 +4,7 @@ and Python test suites with support for SQLAlchemy, SQLModel, and Django. """ -__version__ = "0.3.0" +__version__ = "0.3.1" # Core exports (always available) # Database client exports (choose your preferred client) diff --git a/py_pglite/pytest_plugin.py b/py_pglite/pytest_plugin.py index 8fa1185..ac895c9 100644 --- a/py_pglite/pytest_plugin.py +++ b/py_pglite/pytest_plugin.py @@ -119,28 +119,73 @@ def _should_disable_django_plugin(config: pytest.Config) -> bool: def pytest_runtest_setup(item: pytest.Item) -> None: """Setup each test with perfect framework isolation.""" - # Check for missing dependencies with helpful messages - if item.get_closest_marker("pglite_sqlalchemy") and not HAS_SQLALCHEMY: - pytest.skip( - "🚫 SQLAlchemy not available.\n" - "Install with: pip install 'py-pglite[sqlalchemy]'" - ) - - if item.get_closest_marker("pglite_django") and not HAS_DJANGO: - pytest.skip( - "🚫 Django not available. Install with: pip install py-pglite[django]" - ) - - # Only check for pytest-django if the test is explicitly marked to use it + # Only skip if dependencies are missing AND test is explicitly marked + # (Don't skip auto-marked tests that might work with core fixtures) + + # Check for explicit SQLAlchemy markers only + explicit_sqlalchemy_markers = {"sqlalchemy", "pglite_sqlalchemy"} + if any(item.get_closest_marker(marker) for marker in explicit_sqlalchemy_markers): + if not HAS_SQLALCHEMY and _is_explicitly_marked( + item, explicit_sqlalchemy_markers + ): + print(f"Skipping test {item.name} because SQLAlchemy is not available") + pytest.skip( + "🚫 SQLAlchemy not available.\n" + "Install with: pip install 'py-pglite[sqlalchemy]'" + ) + + # Check for explicit Django markers only + explicit_django_markers = {"django", "pglite_django"} + if any(item.get_closest_marker(marker) for marker in explicit_django_markers): + if not HAS_DJANGO and _is_explicitly_marked(item, explicit_django_markers): + print(f"Skipping test {item.name} because Django is not available") + pytest.skip( + "🚫 Django not available. Install: pip install py-pglite[django]" + ) + + # Check for explicit pytest-django markers if item.get_closest_marker("pytest_django") and not HAS_PYTEST_DJANGO: - pytest.skip( - "🚫 pytest-django not available. Install with: pip install pytest-django" - ) + if _is_explicitly_marked(item, {"pytest_django"}): + pytest.skip( + "🚫 pytest-django not available. Install: pip install pytest-django" + ) # Framework isolation warnings for better DX _check_framework_isolation(item) +def _is_explicitly_marked(item: pytest.Item, marker_names: set[str]) -> bool: + """Check if test is explicitly marked (not auto-marked by plugin).""" + # Simple heuristic: if the test path contains framework names, likely explicit + test_path = str(item.fspath) + + # Framework-specific paths indicate explicit usage + if "sqlalchemy" in marker_names and "sqlalchemy" in test_path.lower(): + return True + if "django" in marker_names and "django" in test_path.lower(): + return True + + # Check if marker has arguments (explicit markers often have config) + for marker_name in marker_names: + marker = item.get_closest_marker(marker_name) + if marker and (marker.args or marker.kwargs): + return True + + # Check for module-level pytestmark (if accessible) + try: + module = getattr(item, "module", None) + if module and hasattr(module, "pytestmark"): + pytestmark = module.pytestmark + if isinstance(pytestmark, list): + return any(mark.name in marker_names for mark in pytestmark) + else: + return pytestmark.name in marker_names + except AttributeError: + pass + + return False + + def _check_framework_isolation(item: pytest.Item) -> None: """Check and warn about potential framework isolation issues.""" fixture_names = getattr(item, "fixturenames", []) @@ -192,7 +237,6 @@ def _auto_mark_test(item: pytest.Item) -> None: "pglite_sqlalchemy_session", "pglite_sqlalchemy_engine", "pglite_config", - "pglite_manager", } if fixture_names & sqlalchemy_fixtures: item.add_marker(pytest.mark.sqlalchemy)