Skip to content

H - #266

Merged
MrIbrahem merged 3 commits into
mainfrom
h
Jul 17, 2026
Merged

H#266
MrIbrahem merged 3 commits into
mainfrom
h

Conversation

@MrIbrahem

@MrIbrahem MrIbrahem commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added automated tools for correcting duplicate redirects and links to redirect pages.
    • Added support for importing page history from an external wiki source.
    • Added workflows for creating missing redirects and performing controlled batch text replacements.
  • Chores

    • Added deployment automation for updating and preparing Python-based tools.
    • Added scheduled maintenance jobs covering synchronization, backups, data checks, and content updates.

@coderabbitai

coderabbitai Bot commented Jul 17, 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: 52 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: 32d1a929-6c62-4d0b-839d-e059ebc0f16e

📥 Commits

Reviewing files that changed from the base of the PR and between ece825f and 189c14a.

📒 Files selected for processing (1)
  • .gitignore

Walkthrough

Adds MediaWiki redirect, import, replacement, and maintenance scripts, plus Toolforge deployment automation, scheduled jobs, and a deployment wrapper for the Python bot.

Changes

MediaWiki maintenance workflows

Layer / File(s) Summary
Redirect repair and creation
src1/md_core/mdpy/fix_duplicate.py, src1/md_core/mdpy/fixred.py, src1/md_core/mdpy/red.py, src1/md_core/mdpy/orred.py
Adds redirect normalization, double-redirect repair, redirect discovery, link rewriting, and redirect-page creation workflows.
Wikipedia history import
src1/md_core/mdpy/imp.py
Adds page selection, pagination, revision retrieval, and conditional history import into mdwiki.
Batch find and replace
src1/md_core/mdpy/replace1.py
Adds configured page-text replacement with logging, search/all-page selection, and processing limits.
Maintenance command runner
src1/md_core/mdpy/mdjobs.sh
Runs maintenance, recheck, title-check, and bot-list commands sequentially.

Toolforge deployment and scheduling

Layer / File(s) Summary
Repository deployment pipeline
toolforge/deploy_repo.sh
Clones a branch, optionally archives and filters source content, copies files, compiles Python files, adjusts permissions, and cleans up.
Scheduled maintenance jobs
toolforge/mdwiki-jobs.yaml, toolforge/mdwiki-jobs.yaml.list
Defines scheduled Toolforge jobs and a command list for database, reference, QID, statistics, redirect, user, and revision maintenance.
Python bot deployment wrapper
toolforge/update_pybot.sh
Configures deployment options and invokes the repository deployment script for the Python bot target.

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

Possibly related PRs

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

Poem

A rabbit hops through redirects bright,
Imports old tales by moonlit light.
Replaces words with careful cheer,
Schedules jobs throughout the year.
Deploys the code with paws so neat—
Maintenance runs on carrot feet!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is too vague to describe the changeset and does not communicate the main change. Use a concise, specific title that summarizes the primary change, such as the new MDWiki maintenance scripts and deployment updates.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 h

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 Toolforge deployment and job configuration scripts, including deploy_repo.sh for cloning and deploying repositories, update_pybot.sh for updating the python bot, and mdwiki-jobs.yaml for scheduling various Toolforge jobs. Feedback focuses on ensuring robust execution and performance: wrapping chained commands in /bin/bash -c within the jobs configuration to prevent execution failures, adding strict bash mode (set -euo pipefail) to the update script, utilizing shallow clones (--depth 1) and more efficient find -exec syntax in the deployment script, and improving file copying and executable checks.

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 toolforge/mdwiki-jobs.yaml
Comment thread toolforge/update_pybot.sh
Comment thread toolforge/deploy_repo.sh
Comment thread toolforge/deploy_repo.sh
Comment thread toolforge/deploy_repo.sh
Comment thread toolforge/deploy_repo.sh
@MrIbrahem
MrIbrahem merged commit 341745d into main Jul 17, 2026
1 of 2 checks passed
@MrIbrahem
MrIbrahem deleted the h branch July 17, 2026 01:24

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

🧹 Nitpick comments (2)
toolforge/deploy_repo.sh (1)

122-122: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optimize file permission updates.

Using \; with -exec forks a new chmod process for every matching file, which can significantly slow down deployments for large repositories. Replacing \; with + will group files and pass them as arguments to a minimal number of chmod invocations.

⚡ Proposed fix for performance optimization
-    find "$TARGET_DIR" -type f ! -name "*.pyc" -exec chmod 770 {} \;
+    find "$TARGET_DIR" -type f ! -name "*.pyc" -exec chmod 770 {} +
🤖 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 `@toolforge/deploy_repo.sh` at line 122, Update the find command’s chmod
invocation to use batched execution with “+” instead of per-file termination
with “\;”, while preserving the existing TARGET_DIR scope, file-type filter, and
*.pyc exclusion.
toolforge/update_pybot.sh (1)

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

Quote the command invocation path to prevent word splitting.

It's a best practice to quote variables representing paths (like $HOME) to handle cases where the path might contain spaces or special characters.

🛠 Proposed fix
-# Run deploy
-$HOME/shs/deploy_repo.sh "$REPO_NAME" "$TARGET_DIR" "$BRANCH"
+# Run deploy
+"$HOME/shs/deploy_repo.sh" "$REPO_NAME" "$TARGET_DIR" "$BRANCH"
🤖 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 `@toolforge/update_pybot.sh` at line 23, Quote the command path in the deploy
invocation within update_pybot.sh by protecting the $HOME-based path from word
splitting, while preserving the existing REPO_NAME, TARGET_DIR, and BRANCH
arguments.

Source: Linters/SAST tools

🤖 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 `@src1/md_core/mdpy/fix_duplicate.py`:
- Around line 19-25: Update the argument-handling logic around the offset
dictionary and sys.argv loop so the parsed offset value is actually applied when
processing redirects, or remove the unused offset option entirely. Ensure
-offset:N and offset:N produce the intended limited processing behavior rather
than always processing every redirect.
- Line 14: Route all Wikipedia API access through the documented shared helpers:
in src1/md_core/mdpy/fix_duplicate.py lines 14-52, replace newapi.AllAPIS and
post_s() with the mdwiki_api.mdwiki_page or apis path; in
src1/md_core/mdpy/red.py lines 60-64, replace the raw requests.Session.post()
call with mdwiki_api.wiki_page.

In `@src1/md_core/mdpy/fixred.py`:
- Around line 105-128: Update the regex substitutions in replace_links2 to pass
re.escape(oldlink) and re.escape(oldlink2) when constructing match patterns, so
link titles with regex metacharacters are matched literally. Use a replacement
callback for the substitutions if newlink can contain backslashes, preserving
the existing replacement text and behavior.
- Around line 157-169: Preserve the original MainPage object used by the save
operation before the links loop, and use a separate variable for each link
metadata dictionary in the loop. Update the final save call to invoke save() on
the preserved MainPage object rather than the loop’s page dictionary.

In `@src1/md_core/mdpy/imp.py`:
- Around line 64-72: Update the save handling in the import flow around
page.save so a failed save does not create or save the User:Mr._Ibrahem/<title>
fallback page via MainPage. Instead, preserve the failure outcome by surfacing
or propagating the save error, leaving the intended target page unsaved without
writing unrelated user-subpage content.

In `@src1/md_core/mdpy/mdjobs.sh`:
- Around line 1-9: Add fail-fast behavior at the start of the maintenance script
so any failing command terminates the job and prevents subsequent commands from
running. Apply the existing command-path quoting consistently to every Python
invocation in the script.

In `@src1/md_core/mdpy/orred.py`:
- Around line 32-36: Update the conditional after page.create in the page
creation flow to check the returned dictionary’s success field explicitly,
logging the success message only when create["success"] is true; preserve the
existing behavior for unsuccessful creation results.
- Line 13: Update the success check around the page.create() result to inspect
create["success"] rather than evaluating the entire create response. Preserve
the existing success logging behavior only when that field indicates success, so
failed creates are not logged as successful.

In `@src1/md_core/mdpy/red.py`:
- Around line 215-283: Replace the duplicated pagination blocks in
src1/md_core/mdpy/red.py lines 215-283 and src1/md_core/mdpy/imp.py lines
168-235 with one advancing loop: handle both "all" and explicit starts through
the same Get_All_pages/work flow, evaluate termination after processing each
batch, and advance using the returned page continuation so each batch is
processed exactly once.

In `@src1/md_core/mdpy/replace1.py`:
- Around line 102-109: Validate the contents loaded by the find-file read before
processing pages, rejecting an empty or whitespace-only find string with the
existing input-error behavior. Add this guard immediately after reading find and
before loading or applying replace, while preserving non-empty find values
unchanged.
- Around line 59-79: Update the save handling around `page.save()` so
`numbers["done"] += 1` occurs only when `save_page is True`, not merely when the
result is truthy. Keep the existing revision and output-file handling aligned
with confirmed saves, ensuring failed saves do not increment the quota or
trigger completion logic.

In `@toolforge/deploy_repo.sh`:
- Line 97: Update the copy command in the deployment script to use the source
directory’s dot path instead of the * wildcard, preserving recursive copying and
the existing target while including hidden files and avoiding failures when the
source directory is empty.

---

Nitpick comments:
In `@toolforge/deploy_repo.sh`:
- Line 122: Update the find command’s chmod invocation to use batched execution
with “+” instead of per-file termination with “\;”, while preserving the
existing TARGET_DIR scope, file-type filter, and *.pyc exclusion.

In `@toolforge/update_pybot.sh`:
- Line 23: Quote the command path in the deploy invocation within
update_pybot.sh by protecting the $HOME-based path from word splitting, while
preserving the existing REPO_NAME, TARGET_DIR, and BRANCH arguments.
🪄 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: 2b152a9e-95df-45f8-a3ba-87cab844484f

📥 Commits

Reviewing files that changed from the base of the PR and between e353001 and ece825f.

📒 Files selected for processing (11)
  • src1/md_core/mdpy/fix_duplicate.py
  • src1/md_core/mdpy/fixred.py
  • src1/md_core/mdpy/imp.py
  • src1/md_core/mdpy/mdjobs.sh
  • src1/md_core/mdpy/orred.py
  • src1/md_core/mdpy/red.py
  • src1/md_core/mdpy/replace1.py
  • toolforge/deploy_repo.sh
  • toolforge/mdwiki-jobs.yaml
  • toolforge/mdwiki-jobs.yaml.list
  • toolforge/update_pybot.sh

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 12

🧹 Nitpick comments (2)
toolforge/deploy_repo.sh (1)

122-122: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optimize file permission updates.

Using \; with -exec forks a new chmod process for every matching file, which can significantly slow down deployments for large repositories. Replacing \; with + will group files and pass them as arguments to a minimal number of chmod invocations.

⚡ Proposed fix for performance optimization
-    find "$TARGET_DIR" -type f ! -name "*.pyc" -exec chmod 770 {} \;
+    find "$TARGET_DIR" -type f ! -name "*.pyc" -exec chmod 770 {} +
🤖 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 `@toolforge/deploy_repo.sh` at line 122, Update the find command’s chmod
invocation to use batched execution with “+” instead of per-file termination
with “\;”, while preserving the existing TARGET_DIR scope, file-type filter, and
*.pyc exclusion.
toolforge/update_pybot.sh (1)

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

Quote the command invocation path to prevent word splitting.

It's a best practice to quote variables representing paths (like $HOME) to handle cases where the path might contain spaces or special characters.

🛠 Proposed fix
-# Run deploy
-$HOME/shs/deploy_repo.sh "$REPO_NAME" "$TARGET_DIR" "$BRANCH"
+# Run deploy
+"$HOME/shs/deploy_repo.sh" "$REPO_NAME" "$TARGET_DIR" "$BRANCH"
🤖 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 `@toolforge/update_pybot.sh` at line 23, Quote the command path in the deploy
invocation within update_pybot.sh by protecting the $HOME-based path from word
splitting, while preserving the existing REPO_NAME, TARGET_DIR, and BRANCH
arguments.

Source: Linters/SAST tools

🤖 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 `@src1/md_core/mdpy/fix_duplicate.py`:
- Around line 19-25: Update the argument-handling logic around the offset
dictionary and sys.argv loop so the parsed offset value is actually applied when
processing redirects, or remove the unused offset option entirely. Ensure
-offset:N and offset:N produce the intended limited processing behavior rather
than always processing every redirect.
- Line 14: Route all Wikipedia API access through the documented shared helpers:
in src1/md_core/mdpy/fix_duplicate.py lines 14-52, replace newapi.AllAPIS and
post_s() with the mdwiki_api.mdwiki_page or apis path; in
src1/md_core/mdpy/red.py lines 60-64, replace the raw requests.Session.post()
call with mdwiki_api.wiki_page.

In `@src1/md_core/mdpy/fixred.py`:
- Around line 105-128: Update the regex substitutions in replace_links2 to pass
re.escape(oldlink) and re.escape(oldlink2) when constructing match patterns, so
link titles with regex metacharacters are matched literally. Use a replacement
callback for the substitutions if newlink can contain backslashes, preserving
the existing replacement text and behavior.
- Around line 157-169: Preserve the original MainPage object used by the save
operation before the links loop, and use a separate variable for each link
metadata dictionary in the loop. Update the final save call to invoke save() on
the preserved MainPage object rather than the loop’s page dictionary.

In `@src1/md_core/mdpy/imp.py`:
- Around line 64-72: Update the save handling in the import flow around
page.save so a failed save does not create or save the User:Mr._Ibrahem/<title>
fallback page via MainPage. Instead, preserve the failure outcome by surfacing
or propagating the save error, leaving the intended target page unsaved without
writing unrelated user-subpage content.

In `@src1/md_core/mdpy/mdjobs.sh`:
- Around line 1-9: Add fail-fast behavior at the start of the maintenance script
so any failing command terminates the job and prevents subsequent commands from
running. Apply the existing command-path quoting consistently to every Python
invocation in the script.

In `@src1/md_core/mdpy/orred.py`:
- Around line 32-36: Update the conditional after page.create in the page
creation flow to check the returned dictionary’s success field explicitly,
logging the success message only when create["success"] is true; preserve the
existing behavior for unsuccessful creation results.
- Line 13: Update the success check around the page.create() result to inspect
create["success"] rather than evaluating the entire create response. Preserve
the existing success logging behavior only when that field indicates success, so
failed creates are not logged as successful.

In `@src1/md_core/mdpy/red.py`:
- Around line 215-283: Replace the duplicated pagination blocks in
src1/md_core/mdpy/red.py lines 215-283 and src1/md_core/mdpy/imp.py lines
168-235 with one advancing loop: handle both "all" and explicit starts through
the same Get_All_pages/work flow, evaluate termination after processing each
batch, and advance using the returned page continuation so each batch is
processed exactly once.

In `@src1/md_core/mdpy/replace1.py`:
- Around line 102-109: Validate the contents loaded by the find-file read before
processing pages, rejecting an empty or whitespace-only find string with the
existing input-error behavior. Add this guard immediately after reading find and
before loading or applying replace, while preserving non-empty find values
unchanged.
- Around line 59-79: Update the save handling around `page.save()` so
`numbers["done"] += 1` occurs only when `save_page is True`, not merely when the
result is truthy. Keep the existing revision and output-file handling aligned
with confirmed saves, ensuring failed saves do not increment the quota or
trigger completion logic.

In `@toolforge/deploy_repo.sh`:
- Line 97: Update the copy command in the deployment script to use the source
directory’s dot path instead of the * wildcard, preserving recursive copying and
the existing target while including hidden files and avoiding failures when the
source directory is empty.

---

Nitpick comments:
In `@toolforge/deploy_repo.sh`:
- Line 122: Update the find command’s chmod invocation to use batched execution
with “+” instead of per-file termination with “\;”, while preserving the
existing TARGET_DIR scope, file-type filter, and *.pyc exclusion.

In `@toolforge/update_pybot.sh`:
- Line 23: Quote the command path in the deploy invocation within
update_pybot.sh by protecting the $HOME-based path from word splitting, while
preserving the existing REPO_NAME, TARGET_DIR, and BRANCH arguments.
🪄 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: 2b152a9e-95df-45f8-a3ba-87cab844484f

📥 Commits

Reviewing files that changed from the base of the PR and between e353001 and ece825f.

📒 Files selected for processing (11)
  • src1/md_core/mdpy/fix_duplicate.py
  • src1/md_core/mdpy/fixred.py
  • src1/md_core/mdpy/imp.py
  • src1/md_core/mdpy/mdjobs.sh
  • src1/md_core/mdpy/orred.py
  • src1/md_core/mdpy/red.py
  • src1/md_core/mdpy/replace1.py
  • toolforge/deploy_repo.sh
  • toolforge/mdwiki-jobs.yaml
  • toolforge/mdwiki-jobs.yaml.list
  • toolforge/update_pybot.sh
🛑 Comments failed to post (12)
src1/md_core/mdpy/fix_duplicate.py (2)

14-14: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== files ==\n'
git ls-files 'src1/md_core/mdpy/*' | sed -n '1,120p'

printf '\n== outlines ==\n'
for f in src1/md_core/mdpy/fix_duplicate.py src1/md_core/mdpy/red.py; do
  echo "--- $f"
  ast-grep outline "$f" --view expanded || true
done

printf '\n== helper search ==\n'
rg -n "mdwiki_api\.wiki_page|mdwiki_api\.mdwiki_page|from .* import apis|def .*apis|class .*apis|newapi\.AllAPIS|Session\.post\(" src1 -S

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 2356


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in src1/md_core/mdpy/fix_duplicate.py src1/md_core/mdpy/red.py; do
  echo "===== $f (lines) ====="
  wc -l "$f"
done

echo "===== fix_duplicate.py ====="
sed -n '1,140p' src1/md_core/mdpy/fix_duplicate.py

echo "===== red.py ====="
sed -n '1,170p' src1/md_core/mdpy/red.py

echo "===== helper definitions ====="
for f in $(git ls-files 'src1/**/mdwiki_api/*.py' 'src1/**/mdwiki_api/**.py' 2>/dev/null | head -n 20); do
  echo "--- $f"
done

rg -n "class NewApi|def .*post|class MainPage|requests.Session|Session\.post|mdwiki_page" src1 -S

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 10047


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in src1/md_core/mdpy/fix_duplicate.py src1/md_core/mdpy/red.py; do
  echo "===== $f (lines) ====="
  wc -l "$f"
done

echo "===== fix_duplicate.py ====="
sed -n '1,140p' src1/md_core/mdpy/fix_duplicate.py

echo "===== red.py ====="
sed -n '1,170p' src1/md_core/mdpy/red.py

echo "===== helper definitions ====="
rg -n "class NewApi|def .*post|class MainPage|requests.Session|Session\.post|mdwiki_page" src1 -S

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 10047


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "===== newapi references ====="
rg -n "\bnewapi\b|from newapi import|import newapi" src1 -S

echo "===== mdwiki_api files ====="
git ls-files 'src1/**/mdwiki_api/*.py' | sed -n '1,120p'

echo "===== wiki_page / mdwiki_page symbols ====="
rg -n "def |class " src1/**/mdwiki_api/*.py -S || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 2143


Route MediaWiki API access through the shared helpers.

  • src1/md_core/mdpy/fix_duplicate.py#L14-L52: replace newapi.AllAPIS/post_s() with the documented mdwiki_api.mdwiki_page or apis path.
  • src1/md_core/mdpy/red.py#L38-L64: replace the raw requests.Session.post() call to the Wikipedia API with mdwiki_api.wiki_page.
📍 Affects 2 files
  • src1/md_core/mdpy/fix_duplicate.py#L14-L14 (this comment)
  • src1/md_core/mdpy/red.py#L60-L64
🤖 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 `@src1/md_core/mdpy/fix_duplicate.py` at line 14, Route all Wikipedia API
access through the documented shared helpers: in
src1/md_core/mdpy/fix_duplicate.py lines 14-52, replace newapi.AllAPIS and
post_s() with the mdwiki_api.mdwiki_page or apis path; in
src1/md_core/mdpy/red.py lines 60-64, replace the raw requests.Session.post()
call with mdwiki_api.wiki_page.

Source: Coding guidelines


19-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Apply or remove the offset option.

The parsed value is never read, so -offset:N still processes every redirect.

🤖 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 `@src1/md_core/mdpy/fix_duplicate.py` around lines 19 - 25, Update the
argument-handling logic around the offset dictionary and sys.argv loop so the
parsed offset value is actually applied when processing redirects, or remove the
unused offset option entirely. Ensure -offset:N and offset:N produce the
intended limited processing behavior rather than always processing every
redirect.
src1/md_core/mdpy/fixred.py (2)

105-128: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the file structure first, then inspect the relevant section.
ast-grep outline src1/md_core/mdpy/fixred.py --view expanded || true

echo "---- imports and symbols ----"
sed -n '1,220p' src1/md_core/mdpy/fixred.py | nl -ba | sed -n '1,220p'

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 575


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- src1/md_core/mdpy/fixred.py lines 1-220 ----"
sed -n '1,220p' src1/md_core/mdpy/fixred.py

echo "---- grep for replace_links2 callers ----"
rg -n "replace_links2\(" -S src1/md_core/mdpy/fixred.py src1 || true

echo "---- grep for oldlink normalization sources ----"
rg -n "normalized|from_to|find_redirects|load_nonredirects" -S src1/md_core/mdpy/fixred.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 8579


Escape link titles before building the regex. Titles with regex metacharacters (for example C++ or Foo(Bar)) can make re.sub fail or replace the wrong text. Use re.escape(oldlink) / re.escape(oldlink2), and switch to a replacement callback if newlink may contain backslashes.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 109-109: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: text.find(f"[[{oldlink}]]")
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)


[warning] 110-110: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: text.find(f"[[{oldlink}|")
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)


[warning] 111-111: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: text.find(f"[[{oldlink2}]]")
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)


[warning] 112-112: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: text.find(f"[[{oldlink2}|")
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)


[warning] 120-120: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.sub(r"[[%s(|]])" % oldlink, r"[[%s\g<1>" % newlink, text, flags=re.IGNORECASE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)


[warning] 123-123: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.sub(r"[[%s(|]])" % oldlink2, r"[[%s\g<1>" % newlink, text, flags=re.IGNORECASE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🤖 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 `@src1/md_core/mdpy/fixred.py` around lines 105 - 128, Update the regex
substitutions in replace_links2 to pass re.escape(oldlink) and
re.escape(oldlink2) when constructing match patterns, so link titles with regex
metacharacters are matched literally. Use a replacement callback for the
substitutions if newlink can contain backslashes, preserving the existing
replacement text and behavior.

Source: Linters/SAST tools


157-169: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Preserve the MainPage object used for saving.

Line 159 replaces page with a link metadata dictionary, so Line 169 calls save() on a dict whenever the page has links.

Proposed fix
-    page = md_MainPage(title, "www", family="mdwiki")
-    exists = page.exists()
-    text = page.get_text()
+    wiki_page = md_MainPage(title, "www", family="mdwiki")
+    exists = wiki_page.exists()
+    text = wiki_page.get_text()
 ...
-        page = links["links"][tt]
-        tit = page["title"]
-        tit2 = normalized.get(page["title"], page["title"])
+        link_data = links["links"][tt]
+        tit = link_data["title"]
+        tit2 = normalized.get(tit, tit)
 ...
-    save_page = page.save(newtext=newtext, summary="Fix redirects")
+    save_page = wiki_page.save(newtext=newtext, summary="Fix redirects")
📝 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.

    for tt in links["links"]:
        # ---
        link_data = links["links"][tt]
        tit = link_data["title"]
        tit2 = normalized.get(tit, tit)
        # ---
        if fixed_tit := from_to.get(tit) or from_to.get(tit2):
            newtext = replace_links2(newtext, tit, fixed_tit)
        elif tit not in nonredirects:
            if tit2 != tit:
                logger.info(f'<<red>> tit:["{tit}"] and tit:["{tit2}"] not in from_to')
    # ---
    save_page = wiki_page.save(newtext=newtext, summary="Fix redirects")
🤖 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 `@src1/md_core/mdpy/fixred.py` around lines 157 - 169, Preserve the original
MainPage object used by the save operation before the links loop, and use a
separate variable for each link metadata dictionary in the loop. Update the
final save call to invoke save() on the preserved MainPage object rather than
the loop’s page dictionary.
src1/md_core/mdpy/imp.py (1)

64-72: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== outline: src1/md_core/mdpy/imp.py ==\n'
ast-grep outline src1/md_core/mdpy/imp.py --view expanded || true

printf '\n== relevant slice: src1/md_core/mdpy/imp.py ==\n'
sed -n '1,140p' src1/md_core/mdpy/imp.py | cat -n

printf '\n== search for related save fallback patterns ==\n'
rg -n "User:Mr\._Ibrahem|Returns the article text after importing the history|page2\.save|save_page is not True|MainPage\(" src1 -S

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 7044


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('src1/md_core/mdpy/imp.py')
print(p.exists(), p.stat().st_size)
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 50 <= i <= 95:
        print(f"{i:4d}: {line}")
PY

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 1793


Don't save failed imports to a user subpage. If page.save() fails, this fallback writes the imported article text to User:Mr._Ibrahem/<title> instead of retrying or surfacing the error, leaving the target page unsaved and creating unrelated wiki content.

🤖 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 `@src1/md_core/mdpy/imp.py` around lines 64 - 72, Update the save handling in
the import flow around page.save so a failed save does not create or save the
User:Mr._Ibrahem/<title> fallback page via MainPage. Instead, preserve the
failure outcome by surfacing or propagating the save error, leaving the intended
target page unsaved without writing unrelated user-subpage content.
src1/md_core/mdpy/mdjobs.sh (1)

1-9: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Fail the maintenance job when any command fails.

Without set -e, an earlier failure is masked by the final command’s exit status and subsequent maintenance continues.

Proposed fix
 #!/bin/bash
+set -euo pipefail
 
-$HOME/local/bin/python3 core8/pwb.py md_core/mdpy/fix_duplicate save
+"$HOME/local/bin/python3" core8/pwb.py md_core/mdpy/fix_duplicate save

Apply the quoting consistently to the remaining commands.

🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 3-3: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 5-5: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 7-7: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 9-9: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 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 `@src1/md_core/mdpy/mdjobs.sh` around lines 1 - 9, Add fail-fast behavior at
the start of the maintenance script so any failing command terminates the job
and prevents subsequent commands from running. Apply the existing command-path
quoting consistently to every Python invocation in the script.
src1/md_core/mdpy/orred.py (2)

13-13: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== repo files of interest ==\n'
git ls-files 'src1/md_core/mdpy/orred.py' 'src1/**/MainPage*' 'src1/**/mdwiki_sql*' 'src1/**/sql_for_mdwiki*' 2>/dev/null || true

printf '\n== outline: src1/md_core/mdpy/orred.py ==\n'
ast-grep outline src1/md_core/mdpy/orred.py --view expanded || true

printf '\n== file: src1/md_core/mdpy/orred.py ==\n'
cat -n src1/md_core/mdpy/orred.py

printf '\n== search for sql_for_mdwiki and mdwiki_sql ==\n'
rg -n "sql_for_mdwiki|mdwiki_sql|select_md_sql" src1 || true

printf '\n== search for MainPage.create definitions/usages ==\n'
rg -n "class MainPage|def create\(" src1 || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 4606


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== inspect nearby code for MainPage.create call site ==\n'
rg -n -A6 -B6 "MainPage\.create|create\(.*\)" src1/md_core/mdpy/orred.py src1 || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 3915


🌐 Web query:

mdwiki_api MainPage.create return value dictionary truthy create summary result

💡 Result:

There is no standard or widely recognized library named mdwiki that contains a method called MainPage.create. MDwiki is predominantly known as a static, client-side Markdown wiki framework (originally by Dynalon) that runs entirely in the browser using HTML5 and JavaScript, requiring no server-side processing or API calls to create pages [1][2][3]. In this context, pages are created by simply adding new.md files to the file system [3][4]. Several other projects use the name mdwiki (or similar variations), such as a Python-based Flask implementation [5][6] and a Go-based project [7][8], but none of these documented repositories expose a library method named MainPage.create. If you are encountering this code, it is likely part of a specific, custom, or internal implementation rather than a public-facing API. Based on standard Python dictionary behavior, if a function returns a dictionary, it is considered truthy if it is non-empty (i.e., contains at least one key-value pair) [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== files under db/mdapi_sql ==\n'
git ls-files 'db/mdapi_sql/**' 'src1/**/db/mdapi_sql/**' 2>/dev/null || true

printf '\n== search for select_md_sql definition and wrappers ==\n'
rg -n -A4 -B4 "def select_md_sql|mdwiki_sql|get_db_categories" . || true

printf '\n== search for mdapi_sql import styles ==\n'
rg -n "from db\.mdapi_sql import sql_for_mdwiki|from db\.mdapi_sql\.services import sql_for_mdwiki|from mdapi_sql import sql_for_mdwiki" . || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== inspect README/docs for mdwiki_sql references ==\n'
rg -n "mdwiki_sql|select_md_sql|sql_for_mdwiki" README* . || true

printf '\n== locate MainPage class reference in repo ==\n'
rg -n "class MainPage|MainPage\(" . || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 32298


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== outline: src/newapi/client_wiki/pages/super_page.py ==\n'
ast-grep outline src/newapi/client_wiki/pages/super_page.py --view expanded || true

printf '\n== relevant slices: src/newapi/client_wiki/pages/super_page.py ==\n'
sed -n '1,220p' src/newapi/client_wiki/pages/super_page.py

printf '\n== mdwiki wrapper: src/mdwiki_api/wiki_page.py ==\n'
sed -n '1,120p' src/mdwiki_api/wiki_page.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 10647


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== create() implementation in src/newapi/client_wiki/pages/super_page.py ==\n'
sed -n '799,874p' src/newapi/client_wiki/pages/super_page.py

printf '\n== any direct type hints/docs for create() return ==\n'
rg -n -A3 -B3 "def create\(" src/newapi/client_wiki/pages/super_page.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 2876


Check create["success"] instead of the whole response here. page.create() returns a non-empty dict on both success and failure, so if create: logs failed creates as successful.

🤖 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 `@src1/md_core/mdpy/orred.py` at line 13, Update the success check around the
page.create() result to inspect create["success"] rather than evaluating the
entire create response. Preserve the existing success logging behavior only when
that field indicates success, so failed creates are not logged as successful.

Source: Coding guidelines


32-36: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and inspect the relevant section.
git ls-files | rg '^src1/md_core/mdpy/orred\.py$' || true
wc -l src1/md_core/mdpy/orred.py
sed -n '1,120p' src1/md_core/mdpy/orred.py

# Find where page.create is used or defined.
rg -n "page\.create\(|def create\(" src1 -g '!**/__pycache__/**'

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 3064


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for page.create usage patterns and any handling of its return value.
rg -n "create\s*=\s*page\.create\(|if\s+page\.create\(|\.get\(\"success\"\)|success\]" src1 -g '!**/__pycache__/**'

# Inspect nearby code in files that use page.create to infer expected return type.
sed -n '220,290p' src1/copy_to_en/medwiki.py
sed -n '170,225p' src1/copy_to_en/mdwikicx.py
sed -n '1,120p' src1/copy_to_en/bot.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 5494


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the implementation or documentation for mdwiki_api.wiki_page.MainPage.create.
fd -a "wiki_page.py" .
rg -n "class MainPage|def create\(" . -g '!*__pycache__*' -g '!*.pyc'

# If the module lives in the repo, inspect the relevant definition area.
for f in $(fd -a "wiki_page.py" .); do
  echo "=== $f ==="
  wc -l "$f"
  sed -n '1,260p' "$f"
done

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 3009


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the MainPage.create implementation.
sed -n '760,860p' src/newapi/client_wiki/pages/super_page.py

# Also inspect any references to a returned "success" field in the same module.
rg -n '"success"|success\)' src/newapi/client_wiki/pages/super_page.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 4060


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the create() return path around the success/failure branches.
sed -n '700,760p' src/newapi/client_wiki/pages/super_page.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 1995


Check create["success"] before logging success.

page.create(...) returns a dict, so if create: also treats {"success": False, ...} as truthy and logs a successful creation on failures.

Suggested change
-        if create:
+        if create.get("success") is True:
             logger.info(f"<<green>>** true .. [[or:{mdtitle}]] ")
📝 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.

    if not page.exists():
        create = page.create(text=text, summary=sus)
        # ---
        if create.get("success") is True:
            logger.info(f"<<green>>** true .. [[or:{mdtitle}]] ")
🤖 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 `@src1/md_core/mdpy/orred.py` around lines 32 - 36, Update the conditional
after page.create in the page creation flow to check the returned dictionary’s
success field explicitly, logging the success message only when
create["success"] is true; preserve the existing behavior for unsuccessful
creation results.
src1/md_core/mdpy/red.py (1)

215-283: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Consolidate the copied pagination into one advancing loop.

Both implementations process batches before entering a second pagination block and mutate okay before progress is evaluated, causing duplicate batches or incomplete "all" runs.

  • src1/md_core/mdpy/red.py#L215-L283: remove both pagination blocks and process each continuation exactly once.
  • src1/md_core/mdpy/imp.py#L168-L235: apply the same single-loop pagination structure.
🧰 Tools
🪛 Ruff (0.15.21)

[error] 227-227: Variable list is shadowing a Python builtin

(A001)


[error] 240-240: Variable list is shadowing a Python builtin

(A001)


[error] 243-243: Variable list is shadowing a Python builtin

(A001)


[error] 245-245: Variable list is shadowing a Python builtin

(A001)


[error] 247-247: Variable list is shadowing a Python builtin

(A001)


[error] 262-262: Variable list is shadowing a Python builtin

(A001)


[error] 278-278: Variable list is shadowing a Python builtin

(A001)

📍 Affects 2 files
  • src1/md_core/mdpy/red.py#L215-L283 (this comment)
  • src1/md_core/mdpy/imp.py#L168-L235
🤖 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 `@src1/md_core/mdpy/red.py` around lines 215 - 283, Replace the duplicated
pagination blocks in src1/md_core/mdpy/red.py lines 215-283 and
src1/md_core/mdpy/imp.py lines 168-235 with one advancing loop: handle both
"all" and explicit starts through the same Get_All_pages/work flow, evaluate
termination after processing each batch, and advance using the returned page
continuation so each batch is processed exactly once.
src1/md_core/mdpy/replace1.py (2)

59-79: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and inspect the relevant region.
ast-grep outline src1/md_core/mdpy/replace1.py --view expanded || true
echo "----"
nl -ba src1/md_core/mdpy/replace1.py | sed -n '1,140p'

echo "---- save() call sites ----"
rg -n "\.save\(" src1/md_core/mdpy -g '*.py' || true

echo "---- MainPage definitions/usages ----"
rg -n "class MainPage|def save\(" src1 -g '*.py' || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 602


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- replace1.py (relevant region) ----"
sed -n '1,140p' src1/md_core/mdpy/replace1.py

echo "---- search for MainPage.save definitions/usages ----"
rg -n "def save\(" src1 -g '*.py' || true
rg -n "class MainPage|class .*Page" src1 -g '*.py' || true

echo "---- search for NewApi and page.save callers ----"
rg -n "NewApi\(|page\.save\(" src1 -g '*.py' || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 6284


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- search for mdwiki_api sources in repo ----"
fd -HI 'mdwiki_page.py|mdwiki_page' . || true

echo "---- search for save_page handling patterns ----"
rg -n "if .*save_page|if .*save\b|== True|is True|newrevid" src1 -g '*.py' || true

echo "---- inspect nearby caller with same pattern ----"
sed -n '1,120p' src1/find_replace_bot/one_job.py

echo "---- inspect another save caller ----"
sed -n '1,120p' src1/md_core/mdpy/fixred.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 7974


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- mdwiki_page.py outline ----"
ast-grep outline src/mdwiki_api/mdwiki_page.py --view expanded || true

echo "---- save() implementation region ----"
rg -n "def save\(" src/mdwiki_api/mdwiki_page.py
sed -n '1,260p' src/mdwiki_api/mdwiki_page.py

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 581


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- inspect md_core/mdpy/imp.py save handling ----"
sed -n '1,120p' src1/md_core/mdpy/imp.py

echo "---- broader patterns around save result checks ----"
rg -n "save_page is not True|if save_page:|if .* is True|return 1|return 0" src1 -g '*.py' || true

echo "---- any docs/comments about page.save return value ----"
rg -n "page\.save|save\(" README.md src1 -g '*.md' -g '*.py' || true

Repository: Mdwiki-TD/mdwiki-python-files

Length of output: 5723


Count only confirmed saves. page.save() is already handled as True/not-True elsewhere in this codebase, so if save_page: here can treat a truthy error payload as success. Move numbers["done"] += 1 behind a strict is True check so failed saves don’t consume the quota and stop the job early.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 77-77: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(file_name[1], "a", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 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 `@src1/md_core/mdpy/replace1.py` around lines 59 - 79, Update the save handling
around `page.save()` so `numbers["done"] += 1` occurs only when `save_page is
True`, not merely when the result is truthy. Keep the existing revision and
output-file handling aligned with confirmed saves, ensuring failed saves do not
increment the quota or trigger completion logic.

102-109: 🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Reject an empty find string before processing pages.

Python inserts the replacement between every character when find == "". With the default 20,000-page limit, an accidentally empty find.txt can cause mass corruption.

     with open(find_file, "r", encoding="utf-8") as file:
         find = file.read()
+    if find == "":
+        raise ValueError("find.txt must not be empty")
📝 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.

    with open(find_file, "r", encoding="utf-8") as file:
        find = file.read()
    if find == "":
        raise ValueError("find.txt must not be empty")
    # ---
    with open(replace_file, "r", encoding="utf-8") as file:
        replace = file.read()
    # ---
    if replace.strip() == "empty":
        replace = ""
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 104-104: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(replace_file, "r", encoding="utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 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 `@src1/md_core/mdpy/replace1.py` around lines 102 - 109, Validate the contents
loaded by the find-file read before processing pages, rejecting an empty or
whitespace-only find string with the existing input-error behavior. Add this
guard immediately after reading find and before loading or applying replace,
while preserving non-empty find values unchanged.
toolforge/deploy_repo.sh (1)

97-97: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Copy hidden files and prevent globbing failures.

Using the * wildcard will skip hidden files (e.g., dotfiles) by default. Furthermore, if $SRC_DIR is empty, * will not expand, and the cp command will fail with a "cannot stat" error.

Use "$SRC_DIR"/. to safely copy all contents, including hidden files, without relying on glob expansion.

💻 Proposed fix
-cp -rf "$SRC_DIR/"* "$TARGET_DIR/" -v
+cp -rf "$SRC_DIR"/. "$TARGET_DIR/" -v
📝 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.

cp -rf "$SRC_DIR"/. "$TARGET_DIR/" -v
🤖 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 `@toolforge/deploy_repo.sh` at line 97, Update the copy command in the
deployment script to use the source directory’s dot path instead of the *
wildcard, preserving recursive copying and the existing target while including
hidden files and avoiding failures when the source directory is empty.

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