codeant-ai-for-open-source[bot] commented on code in PR #36958:
URL: https://github.com/apache/superset/pull/36958#discussion_r2714734041


##########
tests/unit_tests/databases/api_test.py:
##########
@@ -2274,3 +2274,157 @@ def test_schemas_with_oauth2(
             }
         ]
     }
+
+
+def test_export_includes_configuration_method(
+    mocker: MockerFixture, client: Any, full_api_access: None
+) -> None:
+    """
+    Test that exporting a database
+    includes the 'configuration_method' field in the YAML.
+    """
+    import zipfile
+
+    import prison
+
+    from superset.models.core import Database
+
+    # Create a database with a non-default configuration_method
+    db_obj = Database(
+        database_name="export_test_db",
+        sqlalchemy_uri="bigquery://gcp-project-id/",
+        configuration_method="dynamic_form",
+        uuid=UUID("12345678-1234-5678-1234-567812345678"),
+    )
+    db.session.add(db_obj)
+    db.session.commit()
+
+    rison_ids = prison.dumps([db_obj.id])
+    response = client.get(f"/api/v1/database/export/?q={rison_ids}")
+    assert response.status_code == 200
+
+    # Read the zip file from the response
+    buf = BytesIO(response.data)
+    with zipfile.ZipFile(buf) as zf:
+        # Find the database yaml file
+        db_yaml_path = None
+        for name in zf.namelist():
+            if (
+                name.endswith(".yaml")
+                and name.startswith("database_export_")
+                and "/databases/" in name
+            ):
+                db_yaml_path = name
+                break
+        assert db_yaml_path, "Database YAML not found in export zip"
+        with zf.open(db_yaml_path) as f:
+            db_yaml = yaml.safe_load(f.read())
+    # Assert configuration_method is present and correct
+    assert "configuration_method" in db_yaml
+    assert db_yaml["configuration_method"] == "dynamic_form"
+
+
+def test_import_includes_configuration_method(
+    client: Any, full_api_access: None
+) -> None:
+    """
+    Test that importing a database YAML with configuration_method
+    sets the value on the imported DB connection.
+    """
+    from io import BytesIO
+    from unittest.mock import patch
+
+    import yaml
+    from flask import g
+
+    from superset import db, security_manager
+    from superset.models.core import Database
+
+    Database.metadata.create_all(db.session.get_bind())
+
+    metadata = {
+        "version": "1.0.0",
+        "type": "Database",
+        "timestamp": "2025-12-08T18:06:31.356738+00:00",
+    }
+    db_yaml = {
+        "database_name": "Test_Import_Configuration_Method",
+        "sqlalchemy_uri": "bigquery://gcp-project-id/",
+        "cache_timeout": 0,
+        "expose_in_sqllab": True,
+        "allow_run_async": False,
+        "allow_ctas": False,
+        "allow_cvas": False,
+        "allow_dml": False,
+        "allow_csv_upload": False,
+        "extra": {"allows_virtual_table_explore": True},
+        "impersonate_user": False,
+        "uuid": "87654321-4321-8765-4321-876543218765",
+        "configuration_method": "dynamic_form",
+        "version": "1.0.0",
+    }
+    contents = {
+        "metadata.yaml": yaml.safe_dump(metadata),
+        "databases/test.yaml": yaml.safe_dump(db_yaml),
+    }
+
+    with (
+        patch("superset.databases.api.is_zipfile", return_value=True),
+        patch("superset.databases.api.ZipFile"),
+        patch("superset.databases.api.get_contents_from_bundle", 
return_value=contents),
+    ):
+        form_data = {"formData": (BytesIO(b"test"), "test.zip")}
+        response = client.post(
+            "/api/v1/database/import/",
+            data=form_data,
+            content_type="multipart/form-data",
+        )
+        db.session.commit()
+        db.session.remove()
+    assert response.status_code == 200, response.data
+
+    db_obj = (
+        db.session.query(Database)
+        .filter_by(database_name="Test_Import_Configuration_Method")
+        .first()
+    )
+    print("[DEBUG] DB object after import:", db_obj)
+    print("[DEBUG] DB object fields:", {
+        "id": getattr(db_obj, "id", None),
+        "uuid": getattr(db_obj, "uuid", None),
+        "configuration_method": getattr(db_obj, "configuration_method", None),
+        "database_name": getattr(db_obj, "database_name", None),
+    })
+    assert db_obj is not None, "Database not found in SQLAlchemy session after 
import"
+    assert hasattr(db_obj, "configuration_method"), (
+        "'configuration_method' not found on model"
+    )
+    assert db_obj.configuration_method == "dynamic_form", (
+        "Expected configuration_method 'dynamic_form', got "
+        f"{db_obj.configuration_method}"
+    )
+
+    user = getattr(g, "user", None)
+    print("[DEBUG] g.user:", user)

Review Comment:
   **Suggestion:** Accessing `flask.g` without ensuring an application/request 
context will raise "Working outside of application context" (RuntimeError); 
guard access to `g` with `has_request_context()`/`has_app_context()` or catch 
RuntimeError before using it. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Test can raise RuntimeError failing CI.
   - ⚠️ Import test exercises /api/v1/database/import endpoint.
   - ⚠️ Flaky behavior across test runners/environments.
   ```
   </details>
   
   ```suggestion
       from flask import has_request_context, has_app_context
       user = None
       if has_request_context() or has_app_context():
           user = getattr(g, "user", None)
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run the unit test
   
tests/unit_tests/databases/api_test.py::test_import_includes_configuration_method
 (the
   function and the POST call are around lines ~2376-2384). The test performs a
   client.post("/api/v1/database/import/") inside patched contexts (see the 
with(...) block
   at ~2371-2375).
   
   2. After the client.post completes, the test continues outside the request 
lifecycle and
   queries the database via SQLAlchemy (see lines ~2386-2394). Immediately 
after, the test
   executes the lines that access flask.g at 2407: user = getattr(g, "user", 
None). At this
   point there is no active request or app context guaranteed.
   
   3. In a normal pytest/Flask environment, accessing flask.g when there is no 
request/app
   context raises RuntimeError("Working outside of application context"). 
Running pytest will
   reproduce this as a failing test with a RuntimeError raised at
   tests/unit_tests/databases/api_test.py:2407 when getattr(g, ...) is 
evaluated.
   
   4. The concrete fix is to guard access to g using
   flask.has_request_context()/has_app_context() or to perform that logic 
inside an active
   request/app context. If the current access is intentional for tests, leave 
as-is;
   otherwise protect it as in the proposed change.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** tests/unit_tests/databases/api_test.py
   **Line:** 2407:2408
   **Comment:**
        *Possible Bug: Accessing `flask.g` without ensuring an 
application/request context will raise "Working outside of application context" 
(RuntimeError); guard access to `g` with 
`has_request_context()`/`has_app_context()` or catch RuntimeError before using 
it.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to