Skip to content

Z - #262

Merged
MrIbrahem merged 11 commits into
mainfrom
z
Jul 13, 2026
Merged

Z#262
MrIbrahem merged 11 commits into
mainfrom
z

Conversation

@MrIbrahem

@MrIbrahem MrIbrahem commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added database services for managing content, pages, analytics, reports, translation workflows, and Wikidata records.
    • Added lookup, filtering, creation, update, deletion, and summary operations across these areas.
    • Added page and translation statistics, including views, word counts, reference counts, and missing-content reports.
  • Bug Fixes

    • Improved handling of duplicate or conflicting QID mappings by skipping unsafe updates.
    • Improved reference parsing when reference content is empty or missing.
  • Refactor

    • Standardized database service access and error handling.

Commit the comprehensive database service layer that was previously gitignored. Includes modular services for analytics, content, pages, reports, and Wikidata operations. Each service provides high-level database operations with consistent error handling and session management patterns.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@MrIbrahem, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: edc4b173-544a-42bf-a41b-6402b11bbbc2

📥 Commits

Reviewing files that changed from the base of the PR and between 8ee0379 and a359c44.

📒 Files selected for processing (9)
  • docs/MIGRATE_MDAPI_SERVICES.md
  • src/db/mdapi_sql/sql_td_bot.py
  • src/db/tools/models/__init__.py
  • src/db/tools/models/users.py
  • src/db/tools/services/analytics/word_service.py
  • src/db/tools/services/pages/page_service.py
  • src/db/tools/services/pages/user_page_service.py
  • src/db/tools/services/session.py
  • src/db/tools/services/user_service.py

Walkthrough

This change adds SQLAlchemy-backed database services for analytics, content, pages, reports, utilities, and Wikidata, consolidates package exports, adds deletion and session guards, removes the legacy database wrapper, and applies several targeted behavior and typing fixes.

Changes

Database service layer

Layer / File(s) Summary
Analytics service APIs
src/db/tools/services/analytics/*
Adds CRUD, lookup, upsert, aggregation, and package-level exports for analytics records.
Content and page workflows
src/db/tools/services/content/*, src/db/tools/services/pages/*
Adds category, language, project, page, translation, statistics, in-process, and user-page services with consolidated exports.
Deletion, reports, guards, and Wikidata
src/db/tools/services/delete_service.py, reports/*, utils/*, wikidata/*
Adds generic deletion helpers, report services, rollback decorators, and QID-related database APIs.
Legacy behavior and typing updates
.gitignore, src/db/mdapi_sql/*, src/db/tools/services/wikidb.py, src/md_core/*, src/td_core/*
Stops conflicting QID updates, removes script entrypoints and the old database wrapper, and applies focused content, typing, and lookup corrections.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Service
  participant Database
  Caller->>Service: invoke database operation
  Service->>Database: query or mutate ORM record
  Database-->>Service: return committed result
  Service-->>Caller: return record, mapping, or status
Loading

Suggested labels: enhancement, Review effort [1-5]: 4

Poem

I’m a rabbit with services neatly in line,
CRUD carrots and QIDs now happily twine.
Old wrappers hop out, new guards stand tall,
Pages and analytics answer the call.
With logs in my burrow and exports aglow,
I nudge this database garden to grow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is just "Z", which is too vague to describe the pull request's changes. Replace it with a concise sentence that names the main change, such as the new DB service layer or service exports.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 82.07% which is sufficient. The required threshold is 80.00%.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch z

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a comprehensive suite of SQLAlchemy-based database services under src/db/tools/services/ to manage analytics, content, page translations, and Wikidata mappings, alongside minor bug fixes and typing updates in existing scripts. The review feedback identifies several critical issues in these new services: set_page_target and set_user_page_target attempt to modify detached ORM instances without merging them into the active session, and add_translate_row_to_db performs a bulk update but fails to commit the transaction. Additionally, the db_guard_rollback decorator manages an unused session that does not affect the decorated functions, and there is an unused helper function _row_to_dict that should be removed.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/db/tools/services/pages/page_service.py
Comment thread src/db/tools/services/pages/user_page_service.py
Comment thread src/db/tools/services/pages/page_service.py
Comment thread src/db/tools/services/utils/db_guard_model.py
Comment thread src/db/tools/services/pages/pages_users_to_main_service.py

@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: 16

🧹 Nitpick comments (8)
src/db/tools/services/analytics/views_new_service.py (1)

152-158: 🚀 Performance & Scalability | 🔵 Trivial

Use SQL SUM() instead of loading all records into Python.

get_total_views_for_target calls list_views_by_target (which loads all matching ORM objects into memory) then sums r.views in Python. For targets with many records, this is inefficient. A SQL-side aggregation avoids materializing all rows.

♻️ Proposed refactor
 from sqlalchemy import func

 def get_total_views_for_target(
     target: str,
     lang: str | None = None,
 ) -> int:
     """Get total views across all years for a target."""
     with get_session() as session:
         query = session.query(func.coalesce(func.sum(ViewsNewRecord.views), 0)).filter(
             ViewsNewRecord.target == target
         )
         if lang:
             query = query.filter(ViewsNewRecord.lang == lang)
         return query.scalar() or 0
🤖 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/db/tools/services/analytics/views_new_service.py` around lines 152 - 158,
Update get_total_views_for_target to perform the total using a database-side SQL
SUM aggregation filtered by target and optional lang, rather than calling
list_views_by_target or materializing ORM records; return zero when the
aggregate result is null.
src/db/tools/services/analytics/word_service.py (1)

91-107: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Unrestricted setattr from **kwargs allows overwriting any column, including the primary key.

hasattr(orm_obj, key) matches every mapped attribute (w_id included), so a caller passing w_id=... in kwargs would silently reassign the primary key. An explicit allow-list of updatable fields is safer. The same pattern recurs in page_service.update_page and user_page_service.update_user_page.

🔧 Proposed fix
-        for key, value in kwargs.items():
-            if hasattr(orm_obj, key):
-                setattr(orm_obj, key, value)
+        allowed_fields = {"w_title", "w_lead_words", "w_all_words"}
+        for key, value in kwargs.items():
+            if key in allowed_fields:
+                setattr(orm_obj, key, value)
🤖 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/db/tools/services/analytics/word_service.py` around lines 91 - 107,
Restrict the dynamic updates in update_word to an explicit allow-list of mutable
WordRecord fields instead of using hasattr, excluding the primary key w_id and
any other protected attributes. Apply the same allow-list approach in
page_service.update_page and user_page_service.update_user_page, while
preserving existing commit, refresh, and return behavior.
src/db/tools/services/pages/user_page_service.py (1)

1-125: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

This module is a near-complete structural duplicate of page_service.py (same for qid_others_service.py vs qid_service.py).

list_user_pages/list_pages, add_user_page/add_page, insert_user_page_target/insert_page_target, find_user_page_record/find_page_record, etc. are essentially identical logic parameterized only by model class. A generic factory (e.g. a small class/module builder that takes the ORM model and produces these CRUD functions) would remove most of this duplication across both file pairs.

🤖 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/db/tools/services/pages/user_page_service.py` around lines 1 - 125,
Extract the duplicated CRUD logic from list_user_pages, add_user_page, and
insert_user_page_target into a shared generic service/factory parameterized by
the ORM model, then reuse it from the corresponding page_service and qid service
modules. Preserve each module’s existing public function names, signatures,
ordering, filtering, and error behavior while removing the duplicated
implementations.
src/db/tools/services/reports/pages_users_to_main_service.py (1)

55-75: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Unrestricted kwargs update, same pattern as project_service.update_project.

Any attribute matching the model (including the PK id) can be overwritten via setattr. Consider an explicit allow-list of updatable fields (new_target, new_user, new_qid).

🤖 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/db/tools/services/reports/pages_users_to_main_service.py` around lines 55
- 75, The update_pages_users_to_main function currently permits arbitrary model
attributes, including the primary key, to be modified. Restrict its kwargs
update loop to the explicit updatable fields new_target, new_user, and new_qid,
ignoring or rejecting all other keys before calling setattr.
src/db/tools/services/content/project_service.py (1)

63-89: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Unrestricted kwargs update allows overwriting protected fields.

update_project's generic loop lets any caller-supplied key matching an existing attribute (including the primary key g_id) be set via setattr. Consider restricting to an explicit allow-list of updatable fields.

♻️ Proposed fix
+_UPDATABLE_FIELDS = {"g_title", "title"}
+
 def update_project(project_id: int, **kwargs) -> ProjectRecord:
     ...
         for key, value in kwargs.items():
-            if not hasattr(orm_obj, key):
+            if key not in _UPDATABLE_FIELDS or not hasattr(orm_obj, key):
                 continue
🤖 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/db/tools/services/content/project_service.py` around lines 63 - 89,
Restrict the kwargs handled by update_project to an explicit allow-list of
mutable project fields, excluding protected attributes such as g_id and any
primary-key or identity fields. Apply the existing title/g_title validation only
to allowed title fields, and ignore or reject keys outside the allow-list
without assigning them via setattr.
src/db/tools/services/pages/pages_users_to_main_service.py (1)

22-26: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

_row_to_dict is unused dead code.

list_pending constructs dicts manually (lines 56-69) and never calls _row_to_dict. Remove it or refactor list_pending to use it.

♻️ Optional: remove dead code
-def _row_to_dict(row: Any) -> Dict[str, Any]:
-    """Convert a result row (tuple of columns from a join) into a dict."""
-    if hasattr(row, "_asdict"):
-        return dict(row._asdict())
-    return dict(row)
-
-
 def list_pending(lang: str = "All") -> List[Dict[str, Any]]:
🤖 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/db/tools/services/pages/pages_users_to_main_service.py` around lines 22 -
26, Remove the unused _row_to_dict helper, since list_pending currently
constructs its result dictionaries directly and does not call it; leave the
existing list_pending conversion behavior unchanged.
src/db/tools/services/pages/__init__.py (1)

69-119: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

__all__ is not sorted (RUF022).

Ruff flags this list as unsorted. The same applies to __all__ in in_process_service.py, pages_users_to_main_service.py, results_2026_service.py, and translate_type_service.py.

↕️ Optional: sort `__all__`
 __all__ = [
+    "add_in_process",
+    "add_page",
+    "add_translate_row_to_db",
+    "add_translate_type",
+    "add_user_page",
+    "can_translate_full",
+    "can_translate_lead",
+    "check_main_page_exists",
+    "count_category_members",
+    "count_translated",
+    "delete_in_process",
+    "delete_in_process_by_title_user_lang",
+    "delete_page",
+    "delete_translate_type",
+    "delete_user_page",
+    "exists_by_lang_and_category",
+    "find_page_record",
+    "find_user_page_record",
+    "get_in_process",
+    "get_in_process_by_title_user_lang",
+    "get_in_process_counts_by_user",
+    "get_page_by_id",
+    "get_translate_type",
+    "get_translate_type_by_title",
+    "get_user_page",
+    "get_user_page_by_id",
+    "insert_page_target",
+    "insert_user_page_target",
+    "is_in_process",
+    "list_full_enabled_types",
+    "list_in_process",
+    "list_in_process_by_lang",
+    "list_in_process_by_user",
+    "list_lead_enabled_types",
+    "list_new_titles",
+    "list_pages",
+    "list_pages_by_lang_cat",
+    "list_pending",
+    "list_translated",
+    "list_translate_types",
+    "list_user_pages",
+    "missing_by_lang_and_category",
+    "set_page_target",
+    "set_user_page_target",
+    "statics_by_category",
+    "update_in_process",
+    "update_page",
+    "update_translate_type",
+    "update_user_page",
 ]
🤖 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/db/tools/services/pages/__init__.py` around lines 69 - 119, Sort the
exported names in the __all__ list alphabetically in __init__.py and the
corresponding __all__ lists in in_process_service.py,
pages_users_to_main_service.py, results_2026_service.py, and
translate_type_service.py, without changing their contents.

Source: Linters/SAST tools

src/db/tools/services/pages/translate_type_service.py (1)

35-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

list_new_titles wraps the subquery in an unnecessary extra session.query().

existing_titles is already a subquery (line 35). Passing it directly to notin_() avoids the extra nesting.

♻️ Optional: simplify subquery usage
 def list_new_titles() -> List[str]:
     """Return titles in the qids table that are not yet in translate_type."""
     with get_session() as session:
-        existing_titles = session.query(TranslateTypeRecord.tt_title).subquery()
+        existing_titles = session.query(TranslateTypeRecord.tt_title)
         rows = (
             session.query(QidRecord.title)
-            .filter(QidRecord.title.notin_(session.query(existing_titles.c.tt_title)))
+            .filter(QidRecord.title.notin_(existing_titles))
             .distinct()
             .order_by(QidRecord.title.asc())
             .all()
         )
         return [row[0] for row in rows if row[0]]
🤖 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/db/tools/services/pages/translate_type_service.py` around lines 35 - 38,
Update list_new_titles to pass the existing_titles subquery directly to
QidRecord.title.notin_(), removing the unnecessary session.query wrapper while
preserving the existing filtering behavior.
🤖 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 `@src/db/tools/services/analytics/word_service.py`:
- Around line 67-88: Update add_or_update_word to handle the concurrent-insert
IntegrityError during session.commit, matching the existing protection in
add_word. Roll back the session and apply the established duplicate-title
handling behavior instead of allowing the exception to propagate.

In `@src/db/tools/services/content/category_service.py`:
- Around line 18-22: Update add_category and update_category so is_default is
modified only when the caller explicitly provides it, rather than defaulting
omitted values to 0. Preserve the existing behavior for explicitly supplied
values and ensure unrelated field updates do not clear an existing default flag.
- Around line 38-65: Wrap the commit logic in both add_category and
update_category with IntegrityError handling, following the established pattern
in lang_service.add_lang and project_service.add_project. Roll back the session
on failure and raise a clean ValueError for unique category conflicts, while
preserving the existing successful commit and refresh behavior.

In `@src/db/tools/services/content/lang_service.py`:
- Around line 44-65: Add a database-level unique constraint or unique index for
the code column in the LangRecord model and corresponding langs table
DDL/migration. Keep add_lang’s IntegrityError handling intact so duplicate codes
reliably raise the existing ValueError, and ensure add_or_update_lang uses the
constrained schema.

In `@src/db/tools/services/content/project_service.py`:
- Around line 63-89: Update update_project and update_project_title to catch the
database IntegrityError raised during commit when a g_title rename conflicts
with an existing project, translating it into the same friendly ValueError
behavior used by add_project; preserve existing validation and successful-update
behavior, and ensure the session handles the failed transaction appropriately
before returning or propagating other errors.

In `@src/db/tools/services/delete_service.py`:
- Around line 76-102: The delete_user_page_to_main function must return False
when neither PagesUsersToMainRecord nor UserPageRecord exists before deletion.
Track whether at least one row was found, preserve the existing deletion,
commit, rollback, and post-operation verification behavior, and return True only
when a row existed and both records are absent afterward.
- Around line 149-169: Remove the duplicate "delete_record_by_pk" entry from the
__all__ list, keeping one export entry and preserving all other listed symbols.

In `@src/db/tools/services/pages/in_process_service.py`:
- Around line 120-122: Update update_in_process so kwargs are applied only when
the field name is in an explicit whitelist of mutable attributes, excluding
primary-key and immutable fields such as id and add_date; replace the broad
hasattr check while preserving updates for approved fields.

In `@src/db/tools/services/pages/page_service.py`:
- Around line 161-177: Update set_page_target to re-attach the detached
PageRecord within the newly opened session before changing target and pupdate,
by loading the persisted row or merging record and then mutating the attached
instance. Commit the attached entity so the target update is persisted while
preserving the existing rollback and failure behavior.
- Around line 221-233: Move the title underscore-to-space normalization before
the get_word_counts_for_title(title) call in the word == 0 branch, so the lookup
receives the normalized title. Preserve the existing translate_type selection
and retain the remaining parameter normalizations in their current flow.

In `@src/db/tools/services/pages/user_page_service.py`:
- Around line 156-172: Update set_user_page_target so the provided
UserPageRecord is attached to the get_session() session before mutating target
and pupdate. Load the corresponding row in that session or merge record, apply
the updates to the session-managed instance, then preserve the existing commit,
rollback, logging, and boolean return behavior.

In `@src/db/tools/services/reports/pages_users_to_main_service.py`:
- Around line 35-52: Update add_pages_users_to_main so id is required rather
than defaulting to None, and validate it before creating or committing
PagesUsersToMainRecord. Raise a clear ValueError for a missing id, matching the
upfront validation pattern used by other add_* functions, while preserving the
existing persistence behavior for valid ids.

In `@src/db/tools/services/wikidata/qid_others_service.py`:
- Around line 156-191: Update the validation-exception path in update so the
session rolls back before returning False after orm_obj.title and orm_obj.qid
are mutated. Preserve the existing logging and failure return behavior, ensuring
the invalid changes cannot be committed by get_session() on normal exit.

In `@src/db/tools/services/wikidata/qid_service.py`:
- Around line 153-188: Update the validation-failure path in update() to call
session.rollback() before returning False after orm_obj.validate() raises,
preventing get_session() from committing the invalid title and qid mutations.
Apply the same rollback behavior to qid_others_service.update().

In `@src/md_core_helps/one_time/priorviews/bots/gt_blame.py`:
- Line 22: Update the type annotations and defaults for refnames in
match_ref_names(), FindInHistory.__init__(), and search_history() from list[str]
to an appropriate string-keyed mapping type, preserving the existing keyed
membership and access behavior for values from json_langs_by_langs and
json_en_all.

In `@src/md_core_helps/one_time/wikiblame/bot.py`:
- Line 67: Update the content attribute declaration in __init__ to use the
nullable type str | None, reflecting its initial None state; keep the
response.text assignment unchanged and do not re-annotate self.content at that
assignment.

---

Nitpick comments:
In `@src/db/tools/services/analytics/views_new_service.py`:
- Around line 152-158: Update get_total_views_for_target to perform the total
using a database-side SQL SUM aggregation filtered by target and optional lang,
rather than calling list_views_by_target or materializing ORM records; return
zero when the aggregate result is null.

In `@src/db/tools/services/analytics/word_service.py`:
- Around line 91-107: Restrict the dynamic updates in update_word to an explicit
allow-list of mutable WordRecord fields instead of using hasattr, excluding the
primary key w_id and any other protected attributes. Apply the same allow-list
approach in page_service.update_page and user_page_service.update_user_page,
while preserving existing commit, refresh, and return behavior.

In `@src/db/tools/services/content/project_service.py`:
- Around line 63-89: Restrict the kwargs handled by update_project to an
explicit allow-list of mutable project fields, excluding protected attributes
such as g_id and any primary-key or identity fields. Apply the existing
title/g_title validation only to allowed title fields, and ignore or reject keys
outside the allow-list without assigning them via setattr.

In `@src/db/tools/services/pages/__init__.py`:
- Around line 69-119: Sort the exported names in the __all__ list alphabetically
in __init__.py and the corresponding __all__ lists in in_process_service.py,
pages_users_to_main_service.py, results_2026_service.py, and
translate_type_service.py, without changing their contents.

In `@src/db/tools/services/pages/pages_users_to_main_service.py`:
- Around line 22-26: Remove the unused _row_to_dict helper, since list_pending
currently constructs its result dictionaries directly and does not call it;
leave the existing list_pending conversion behavior unchanged.

In `@src/db/tools/services/pages/translate_type_service.py`:
- Around line 35-38: Update list_new_titles to pass the existing_titles subquery
directly to QidRecord.title.notin_(), removing the unnecessary session.query
wrapper while preserving the existing filtering behavior.

In `@src/db/tools/services/pages/user_page_service.py`:
- Around line 1-125: Extract the duplicated CRUD logic from list_user_pages,
add_user_page, and insert_user_page_target into a shared generic service/factory
parameterized by the ORM model, then reuse it from the corresponding
page_service and qid service modules. Preserve each module’s existing public
function names, signatures, ordering, filtering, and error behavior while
removing the duplicated implementations.

In `@src/db/tools/services/reports/pages_users_to_main_service.py`:
- Around line 55-75: The update_pages_users_to_main function currently permits
arbitrary model attributes, including the primary key, to be modified. Restrict
its kwargs update loop to the explicit updatable fields new_target, new_user,
and new_qid, ignoring or rejecting all other keys before calling setattr.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ef77e7b1-29a6-459a-a036-0c70b480a232

📥 Commits

Reviewing files that changed from the base of the PR and between e9d714b and 8ee0379.

📒 Files selected for processing (38)
  • .gitignore
  • src/db/mdapi_sql/services/sql_qids.py
  • src/db/mdapi_sql/services/sql_qids_others.py
  • src/db/mdapi_sql/wikidb.py
  • src/db/tools/services/analytics/__init__.py
  • src/db/tools/services/analytics/assessment_service.py
  • src/db/tools/services/analytics/enwiki_pageview_service.py
  • src/db/tools/services/analytics/mdwiki_revid_service.py
  • src/db/tools/services/analytics/refs_count_service.py
  • src/db/tools/services/analytics/views_new_service.py
  • src/db/tools/services/analytics/word_service.py
  • src/db/tools/services/content/__init__.py
  • src/db/tools/services/content/category_service.py
  • src/db/tools/services/content/lang_service.py
  • src/db/tools/services/content/project_service.py
  • src/db/tools/services/delete_service.py
  • src/db/tools/services/pages/__init__.py
  • src/db/tools/services/pages/in_process_service.py
  • src/db/tools/services/pages/missing_stats_service.py
  • src/db/tools/services/pages/page_service.py
  • src/db/tools/services/pages/pages_users_to_main_service.py
  • src/db/tools/services/pages/results_2026_service.py
  • src/db/tools/services/pages/translate_type_service.py
  • src/db/tools/services/pages/user_page_service.py
  • src/db/tools/services/pages_query_service.py
  • src/db/tools/services/reports/__init__.py
  • src/db/tools/services/reports/pages_users_to_main_service.py
  • src/db/tools/services/utils/__init__.py
  • src/db/tools/services/utils/db_guard_model.py
  • src/db/tools/services/wikidata/__init__.py
  • src/db/tools/services/wikidata/allqid_service.py
  • src/db/tools/services/wikidata/qid_others_service.py
  • src/db/tools/services/wikidata/qid_service.py
  • src/md_core/mdpy/fixref/fixref_text_new.py
  • src/md_core/p11143_bot/wd_helps.py
  • src/md_core_helps/one_time/priorviews/bots/gt_blame.py
  • src/md_core_helps/one_time/wikiblame/bot.py
  • src/td_core/fix_user_pages/fix_it_db.py
💤 Files with no reviewable changes (4)
  • .gitignore
  • src/db/mdapi_sql/wikidb.py
  • src/db/mdapi_sql/services/sql_qids_others.py
  • src/db/mdapi_sql/services/sql_qids.py

Comment thread src/db/tools/services/analytics/word_service.py
Comment thread src/db/tools/services/content/category_service.py
Comment thread src/db/tools/services/content/category_service.py
Comment thread src/db/tools/services/content/lang_service.py
Comment thread src/db/tools/services/content/project_service.py
Comment thread src/db/tools/services/reports/pages_users_to_main_service.py
Comment thread src/db/tools/services/wikidata/qid_others_service.py
Comment thread src/db/tools/services/wikidata/qid_service.py
Comment thread src/md_core_helps/one_time/priorviews/bots/gt_blame.py
Comment thread src/md_core_helps/one_time/wikiblame/bot.py
@MrIbrahem
MrIbrahem merged commit b9c865e into main Jul 13, 2026
1 of 2 checks passed
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