Skip to content

Code consistency#358

Open
PGijsbers wants to merge 12 commits into
mainfrom
code-consistency
Open

Code consistency#358
PGijsbers wants to merge 12 commits into
mainfrom
code-consistency

Conversation

@PGijsbers

Copy link
Copy Markdown
Contributor

Several changes to make the code base more consistent in naming, typing, and use of connection vs session.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @PGijsbers, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The pull request migrates database access from AsyncConnection to AsyncSession, including SQL parameter handling and shared identifier types. FastAPI dependencies, routers, schemas, user state, and response field mappings are updated accordingly. Test fixtures now provide connection and savepoint-backed session variants with dependency overrides, while database and router tests use the new fixtures. Test documentation is updated to describe transaction visibility and rollback behavior.

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too generic to convey the main change in the pull request. Use a specific title such as 'Migrate database access to AsyncSession and standardize identifier types'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is clearly related to the codebase-wide naming, typing, and session consistency changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch code-consistency

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.70115% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.44%. Comparing base (7f6ace1) to head (19b9557).

Files with missing lines Patch % Lines
src/routers/dependencies.py 44.44% 5 Missing ⚠️
tests/conftest.py 95.34% 2 Missing ⚠️
src/database/users.py 90.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #358       +/-   ##
===========================================
+ Coverage   77.60%   94.44%   +16.83%     
===========================================
  Files          77       77               
  Lines        3774     3833       +59     
  Branches      247      248        +1     
===========================================
+ Hits         2929     3620      +691     
+ Misses        759      145      -614     
+ Partials       86       68       -18     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routers/datasets.py (1)

137-156: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Invalid Python 3 except clause except DatasetNotFoundError, DatasetNoAccessError: is syntax-invalid and will stop src/routers/datasets.py from loading. Use except (DatasetNotFoundError, DatasetNoAccessError): instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routers/datasets.py` around lines 137 - 156, Fix the invalid exception
syntax in the untag_dataset function by changing the except clause to catch
DatasetNotFoundError and DatasetNoAccessError as a tuple: except
(DatasetNotFoundError, DatasetNoAccessError):.
🧹 Nitpick comments (1)
src/database/tasks.py (1)

21-149: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Inconsistent DB-handle parameter naming (expdb vs session) undermines this PR's consistency goal.

Within this same file, most functions take expdb: AsyncSession (Lines 21, 35, 47, 61, 82, 104-106, 121, 135-137) while get_tags and tag take session: AsyncSession (Lines 152, 162). This split isn't tied to raw-SQL vs ORM usage either — src/database/setups.py's get() (also raw SQL via session.execute) uses session, while src/database/runs.py/flows.py's get() use expdb. Since this PR's explicit goal is naming/usage consistency, consider standardizing on one parameter name across all database helper modules.

Also applies to: 152-176

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/database/tasks.py` around lines 21 - 149, Standardize the database-handle
parameter name across the helper modules to match the consistency goal. Rename
the inconsistent `expdb`/`session` parameters in `get`, `get_task_types`,
`get_task_type`, `get_task_type_name`, `get_task_evaluation_measure`,
`get_input_for_task_type`, `get_input_for_task`,
`get_task_type_inout_with_template`, `get_tags`, and `tag`, updating all
internal references and call sites consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/development/tests.md`:
- Around line 95-106: Update the AsyncConnection.execute calls in
test_python_and_php to use the parameters= keyword instead of params= for both
the dataset INSERT and DELETE statements.

In `@src/routers/tasks.py`:
- Around line 472-474: In the loop building filled_templates, replace the unused
name variable in the input_templates iteration with an underscore while
retaining template for fill_template.

In `@tests/routers/users_delete_test.py`:
- Around line 55-61: Update the stale comment near the user setup in the test to
replace the old user_test fixture reference with userdb_session, and accurately
state that rollback is performed by the dependent userdb_connection fixture.
Keep the comment consistent with the current fixture names and behavior.

---

Outside diff comments:
In `@src/routers/datasets.py`:
- Around line 137-156: Fix the invalid exception syntax in the untag_dataset
function by changing the except clause to catch DatasetNotFoundError and
DatasetNoAccessError as a tuple: except (DatasetNotFoundError,
DatasetNoAccessError):.

---

Nitpick comments:
In `@src/database/tasks.py`:
- Around line 21-149: Standardize the database-handle parameter name across the
helper modules to match the consistency goal. Rename the inconsistent
`expdb`/`session` parameters in `get`, `get_task_types`, `get_task_type`,
`get_task_type_name`, `get_task_evaluation_measure`, `get_input_for_task_type`,
`get_input_for_task`, `get_task_type_inout_with_template`, `get_tags`, and
`tag`, updating all internal references and call sites consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4a86116c-015e-494e-8247-fbe17668d0cd

📥 Commits

Reviewing files that changed from the base of the PR and between 7f6ace1 and 19b9557.

📒 Files selected for processing (57)
  • docs/development/tests.md
  • src/core/access.py
  • src/database/datasets.py
  • src/database/evaluations.py
  • src/database/flows.py
  • src/database/qualities.py
  • src/database/runs.py
  • src/database/setups.py
  • src/database/studies.py
  • src/database/tasks.py
  • src/database/users.py
  • src/routers/datasets.py
  • src/routers/dependencies.py
  • src/routers/estimation_procedure.py
  • src/routers/evaluations.py
  • src/routers/flows.py
  • src/routers/qualities.py
  • src/routers/runs.py
  • src/routers/schemas/__init__.py
  • src/routers/schemas/core.py
  • src/routers/schemas/datasets.py
  • src/routers/schemas/flows.py
  • src/routers/schemas/runs.py
  • src/routers/schemas/setups.py
  • src/routers/schemas/study.py
  • src/routers/schemas/tasks.py
  • src/routers/setups.py
  • src/routers/study.py
  • src/routers/tasks.py
  • src/routers/tasktype.py
  • src/routers/users.py
  • tests/conftest.py
  • tests/database/flows_test.py
  • tests/database/runs_test.py
  • tests/dependencies/fetch_user_test.py
  • tests/routers/dataset_tag_test.py
  • tests/routers/dataset_untag_test.py
  • tests/routers/datasets_features_test.py
  • tests/routers/datasets_get_test.py
  • tests/routers/datasets_list_datasets_test.py
  • tests/routers/datasets_qualities_test.py
  • tests/routers/datasets_status_test.py
  • tests/routers/flows_exists_test.py
  • tests/routers/flows_get_test.py
  • tests/routers/qualities_list_test.py
  • tests/routers/runs_get_test.py
  • tests/routers/runs_trace_test.py
  • tests/routers/setups_get_test.py
  • tests/routers/setups_tag_test.py
  • tests/routers/setups_untag_test.py
  • tests/routers/study_attach_test.py
  • tests/routers/tag_test_helper.py
  • tests/routers/task_get_test.py
  • tests/routers/task_list_test.py
  • tests/routers/task_tag_test.py
  • tests/routers/task_type_get_test.py
  • tests/routers/users_delete_test.py

Comment thread docs/development/tests.md
Comment on lines +95 to +106
async def test_python_and_php(py_api: httpx.AsyncClient, php_api: httpx.AsyncClient, expdb_connection: AsyncConnection) -> None:
await expdb_connection.execute(text("INSERT INTO dataset ..."), params=...) # Insert dataset with id 42
await expdb_connection.commit() # We need to persist the data in the database, because the PHP REST API cannot see our transaction

response = await php_api.get("/datasets/42") # The PHP REST API can see the dataset, because it exists in the database
response = await py_api.get("/datasets/42") # The Python REST API can see the dataset also

# We need to clean up after ourselves, otherwise the test has side effects.
# This isn't a great pattern, prefer instead the use of context managers which will execute the delete statements even if unexpected exceptions occur.
await expdb_connection.execute(text("DELETE FROM dataset ..."), params=...)
await expdb_connection.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check SQLAlchemy version and AsyncConnection.execute signature
rg -n "sqlalchemy" pyproject.toml uv.lock requirements*.txt 2>/dev/null | head -20
python -c "import inspect; from sqlalchemy.ext.asyncio import AsyncConnection; print(inspect.signature(AsyncConnection.execute))" 2>/dev/null || echo "Could not inspect AsyncConnection.execute"

Repository: openml/server-api

Length of output: 1929


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate dependency declarations for SQLAlchemy
git ls-files | rg '^(pyproject\.toml|uv\.lock|requirements.*\.txt|poetry\.lock|Pipfile.lock)$' || true

for f in pyproject.toml uv.lock requirements.txt requirements-dev.txt requirements*.txt poetry.lock Pipfile.lock; do
  if [ -f "$f" ]; then
    echo "### $f"
    rg -n "sqlalchemy|SQLAlchemy" "$f" || true
  fi
done

# Inspect the installed SQLAlchemy signature if available in the environment
python3 - <<'PY'
import inspect
try:
    from sqlalchemy.ext.asyncio import AsyncConnection
    print(inspect.signature(AsyncConnection.execute))
except Exception as e:
    print(f"Could not inspect AsyncConnection.execute: {e}")
PY

Repository: openml/server-api

Length of output: 1994


🌐 Web query:

SQLAlchemy AsyncConnection.execute parameters params signature AsyncSession.execute docs

💡 Result:

In SQLAlchemy, the execute method signatures differ between AsyncConnection and AsyncSession, specifically regarding the parameter argument name. AsyncConnection.execute The signature for AsyncConnection.execute is: async def execute(self, statement: Executable, parameters: _CoreAnyExecuteParams | None = None, *, execution_options: CoreExecuteOptionsParameter | None = None) -> CursorResult[Any] The parameter holding the bind values is named parameters [1][2]. It accepts either a single dictionary (for a single execution) or a sequence of dictionaries (for executemany behavior) [1][2]. AsyncSession.execute The signature for AsyncSession.execute uses params instead of parameters: async def execute(self, statement: Executable, params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, bind_arguments: Optional[_BindArguments] = None, kw: Any) -> Result[Unpack[TupleAny]] In the AsyncSession, the argument is named params [3]. This aligns with the interface of the synchronous ORM Session.execute method [3]. Summary of Key Differences Component | Argument Name for Bind Values | Reference --- | --- | --- AsyncConnection.execute | parameters [1] | [1], [4] AsyncSession.execute | params [3] | [3] Both methods are awaitable and return result objects [1][3]. When using these methods, ensure you use the argument name specific to the object type you are interacting with (Connection vs. Session) to avoid keyword argument errors.

Citations:


Use parameters= for AsyncConnection.execute(). expdb_connection is an AsyncConnection, so lines 96 and 104 should pass parameters=; params= is for AsyncSession.execute() and will raise a TypeError here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/development/tests.md` around lines 95 - 106, Update the
AsyncConnection.execute calls in test_python_and_php to use the parameters=
keyword instead of params= for both the dataset INSERT and DELETE statements.

Comment thread src/routers/tasks.py
Comment on lines +472 to +474
filled_templates = []
for name, template in input_templates:
filled_templates.append(await fill_template(template, task, task_inputs, expdb))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Unused loop variable name (Ruff B007).

name from input_templates is never used inside the loop body; only template is used.

🔧 Proposed fix
     filled_templates = []
-    for name, template in input_templates:
+    for _name, template in input_templates:
         filled_templates.append(await fill_template(template, task, task_inputs, expdb))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
filled_templates = []
for name, template in input_templates:
filled_templates.append(await fill_template(template, task, task_inputs, expdb))
filled_templates = []
for _name, template in input_templates:
filled_templates.append(await fill_template(template, task, task_inputs, expdb))
🧰 Tools
🪛 Ruff (0.15.20)

[warning] 473-473: Loop control variable name not used within loop body

(B007)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routers/tasks.py` around lines 472 - 474, In the loop building
filled_templates, replace the unused name variable in the input_templates
iteration with an underscore while retaining template for fill_template.

Source: Linters/SAST tools

Comment on lines +55 to +61
params={"username": username, "email": email, "api_key": api_key},
)
uid_row = await user_test.execute(text("SELECT LAST_INSERT_ID() AS id"))
uid_row = await userdb_session.execute(text("SELECT LAST_INSERT_ID() AS id"))
(new_id,) = uid_row.one()
await user_test.execute(
await userdb_session.execute(
text("INSERT INTO users_groups (user_id, group_id) VALUES (:uid, :gid)"),
parameters={"uid": new_id, "gid": UserGroup.READ_WRITE.value},
params={"uid": new_id, "gid": UserGroup.READ_WRITE.value},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update stale comment referencing the old user_test fixture name.

Line 64 still references user_test as the fixture that handles rollback, but this PR renamed it to userdb_session. The actual rollback is performed by the userdb_connection fixture that userdb_session depends on.

📝 Proposed fix
     return DisposableUser(user_id=new_id, api_key=api_key)
-    # No explicit teardown: the ``user_test`` fixture rolls back at the end
+    # No explicit teardown: the ``userdb_connection`` fixture rolls back at the end
     # of the test, which removes the rows inserted above.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/routers/users_delete_test.py` around lines 55 - 61, Update the stale
comment near the user setup in the test to replace the old user_test fixture
reference with userdb_session, and accurately state that rollback is performed
by the dependent userdb_connection fixture. Keep the comment consistent with the
current fixture names and behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant