Stacks

Extract a Shared Helper From Duplicated Code in Python with Atlas (2026)

Updated 7 min read

Atlas extracts a shared helper from duplicated Python code by treating duplication as a semantic problem rather than a textual one. The copies usually differ in variable names, so grep never finds them. Atlas asks codebase_search for the behavior instead of the exact code, reads each hit to confirm the copies are genuinely equivalent, creates the shared module with the write tool, and replaces each duplicate with a call using apply_patch, one file per patch, running pytest after every swap.

Why does grep fail to find duplicated Python code?

Grep fails on Python duplication because 2 copies of the same logic almost never match textually. The same retry loop appears in src/api/client.py with a variable named resp and in src/workers/sync.py with one named response, and a regex that finds 1 of them misses the other. Duplication is a semantic problem.

Python makes this worse than most languages, because the idioms that get copy-pasted are short and highly variable in surface form: a try or except block around an HTTP call, a datetime normalization, a dict-to-model coercion. Two copies can be logically identical and share almost no tokens. Atlas therefore does not start with grep. It asks codebase_search for the behavior, and the semantic index returns the near-duplicate implementations by meaning. Grep still has a role, but at the end, as verification, not at the start as discovery.

How does codebase_search find near-duplicate Python implementations?

Atlas searches Python code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, and indexes code by AST declarations using tree-sitter rather than blind line windows. Asking codebase_search to retry an HTTP request with exponential backoff returns the whole def, from 3 different modules, not fragments.

The tree-sitter indexing is what makes the results usable for a Python extraction. The retrieved unit is the declaration, so you get the complete function including its except clauses and its return, rather than a window sliced through the middle of a with block. That is the difference between confirming two copies are equivalent and guessing. If your Python source must stay on your machine, Atlas can build the same index with local Ollama embeddings, so the semantic search runs without code leaving the box.

How do you confirm two Python copies are actually the same before collapsing them?

Atlas reads each codebase_search hit and confirms the copies are genuinely equivalent before collapsing them. Two Python functions that look like the same retry loop can differ in one clause, one swallows a ValueError and the other re-raises, and collapsing them into 1 helper would silently change behavior in both callers.

This is the step people skip, and it is the one that turns a cleanup into an incident. Atlas reads the full body of each candidate in src/api/client.py, src/workers/sync.py, and wherever else the semantic index found them, and compares them clause by clause. Where they genuinely diverge, the divergence becomes a parameter of the new helper, or the copy is left alone. Where they are equivalent, extraction proceeds. Reading before writing is the entire safeguard here.

How does Atlas create the shared Python helper module?

Atlas creates the shared Python helper at step 3 of the workflow, using the write tool, which shows the full diff in the permission prompt before the file is created. A new src/common/retry.py appears in the prompt in its entirety, so you approve its signature and exception handling before anything lands on disk.

The permission prompt is the design review. You see the def, the parameters that absorbed the differences between the copies, the exception handling, and the type hints, and you approve or you do not. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs, and Atlas can draft the extraction in a read-only plan agent and ask before switching to a build agent, so the helper's shape is agreed before any caller is touched.

Why does Atlas replace each Python duplicate with one apply_patch per file?

Atlas replaces each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible. Collapsing 4 copies into src/common/retry.py produces 4 patches, and a mistake in the third does not require unpicking the first two.

One giant patch across every caller is a single decision you cannot partially undo. Per-file patches are four decisions. Atlas applies the patch to src/api/client.py, runs pytest through the bash tool, confirms green, and only then moves to src/workers/sync.py. Because apply_patch anchors each hunk on context lines and refuses to apply against a drifted file, a ruff format run between patches cannot cause a silent clobber. Atlas also snapshots file changes as git patches, so any individual swap can be rolled back.

How do you verify a Python helper extraction is complete?

Atlas runs pytest through the bash tool after every swap, then finishes by grepping for any surviving copy. An extraction that leaves 1 duplicate behind in src/workers/sync.py has not reduced duplication, it has added a fifth implementation of the same logic.

The pytest run after each apply_patch is what localizes a break to the swap that caused it, instead of leaving you with a red suite and four suspect files. The final grep is the completeness check: search for a distinctive token from the old copied body, and confirm zero hits outside src/common/retry.py. Run ruff format over the touched files so the diff shows the extraction rather than line-wrapping churn, and let uv keep the environment consistent while pytest runs.

Step by step

  1. 01Run atlas in a repo with a pyproject.toml or requirements.txt and let Atlas read your package layout, virtualenv, and installed dependencies.
  2. 02Ask codebase_search for the behavior (not the exact code) to surface near-duplicate Python implementations that grep would miss because the copies differ in variable names.
  3. 03Read each hit and confirm the copies are genuinely equivalent before collapsing them; a different except clause means they are not.
  4. 04Create the shared helper with write, for example src/common/retry.py, which shows the full diff in the permission prompt before the file is created.
  5. 05Replace each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible.
  6. 06Run pytest through the bash tool after every swap, not once at the end, so a break is localized to the patch that caused it.
  7. 07Run ruff format over the touched Python files so the diff shows the extraction rather than formatting churn.
  8. 08Finish by grepping for any surviving copy of the old logic and confirm zero hits outside the new helper module.

Frequently asked questions

how to find duplicated logic in a Python codebase when grep does not work
Ask codebase_search for the behavior rather than the exact code. Atlas searches with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so two copies of the same retry loop are found even when one names its variable resp and the other names it response.
how do I extract a shared helper from duplicated Python code safely
Find the copies with codebase_search, read each one to confirm they are genuinely equivalent, create the helper with the write tool, then replace each duplicate with a call using apply_patch, one file per patch, running pytest after every swap.
why one apply_patch per file instead of a single big patch
So each swap is independently reviewable and revertible. A mistake in the third caller does not require unpicking the first two, and pytest after each patch localizes any break to the change that caused it.
what stops Atlas from collapsing two Python functions that are not really the same
The documented workflow reads each hit and confirms equivalence before collapsing. Two copies that differ in one except clause, one swallowing a ValueError and the other re-raising, are not equivalent, and the divergence becomes a parameter or the copy is left alone.
does Atlas work with uv, pytest, and ruff format
Yes. Start atlas in a repo with a pyproject.toml or requirements.txt and it reads your package layout, virtualenv, and installed dependencies. It runs uv, pytest, and ruff format through the bash tool, which is a real shell.
can I run semantic code search on Python without sending code to a third party
Yes. Atlas can build its code index with local Ollama embeddings, keeping code off third-party servers. The index is built from AST declarations using tree-sitter, so retrieval still returns whole functions rather than blind line windows.
will Atlas show me the new helper module before creating it
Yes. The write tool shows the full diff in the permission prompt before the file is created, so you approve the helper's signature and behavior first. Atlas can also draft the extraction in a read-only plan agent before switching to a build agent.

Try Atlas in your terminal

The terminal-native AI coding agent. Free core, single binary.

Install Atlas

Related guides

Extract a Shared Helper from Duplicated Code with Atlas (2026 Workflow)

How to extract a shared helper from duplicated code with Atlas in 2026: codebase_search finds the copies by meaning, write creates the module, apply_patch swaps each call.

Atlas for Python in 2026

Atlas is a terminal-native AI coding agent for Python in 2026. Run it in a repo with a pyproject.toml or requirements.txt and review every diff before it lands.

Document a Python Module With a README Using Atlas (2026)

Atlas writes Python docs from source, not memory: lsp documentSymbol lists the real exports, read supplies behavior, and every code sample is proven with pytest.

Run Atlas Headless in CI in a Python Repo: The 2026 Guide to atlas run

Run Atlas headless in CI on a Python repo in 2026. Use atlas run with --format json, pre-approve tools, and gate the pipeline on pytest, uv, and ruff format.

Audit a Python Repo with Parallel Subagents in Atlas (2026)

Audit a Python repo with parallel Atlas subagents in 2026. Slice by package, launch read-only explore tasks, and merge findings without flooding your context.

Trace a Runtime Bug from a Python Stack Trace with Atlas in 2026

Go from a Python traceback to the responsible line in 2026 with no debugger attached: Atlas reads each frame at its offset, greps for the message, and walks callers with lsp.

Add a Regression Test for a Bug Fix in Python with Atlas (2026)

Red first, then green. Atlas writes a failing pytest case, proves it fails with the bash tool exit code, applies the fix with edit, and re-runs the same command.

Upgrade Python Dependencies and Fix Breakage with Atlas in 2026

In 2026, Python developers use Atlas to upgrade dependencies like Django or FastAPI, automatically fixing compile and test failures with `uv`, `pytest`, and `ruff format`.

Browse this resource hub