Product

Clean up repeated SQLAlchemy 1.4 to 2.0 migration edits on a local branch

A deterministic paid workflow for the SQLAlchemy cleanup that is repetitive, review-heavy, and safe to stage: Query.get, select([..]), simple string relationship paths, declarative imports, and legacy DML constructor syntax.

Start here

Buy the apply workflow when the scan shows repeated supported cleanup.

The pack turns the supported scan buckets into a preview/apply migration run with a report your team can review before merge.

  • Local workflow with no repo upload.
  • Previewable changes and a structured report.
  • Manual-review findings stay visible instead of hidden.

Price: $299.99 per team.

Secure checkout is handled by Stripe.

Trust boundary

Scope and validation

  • Run on a branch and review the documented scope before applying changes.
  • The public repo is scanner-first and does not expose the full paid apply engine.
  • Examples establish only the cases shown. Run your own application tests before merging.

What this fixes

  • session.query(Model).get(pk) to Session.get(Model, pk).
  • select([columns]) legacy list syntax to direct select(columns).
  • Simple string joins and loader options when the root mapped class is obvious.
  • sqlalchemy.ext.declarative imports for declarative_base and declared_attr.
  • Direct insert/update/delete constructor kwargs moved onto statement methods.

After purchase, you receive

  • Commercial ZIP with the paid cleanup workflow and local CLI.
  • Preview/apply commands, diff output, and JSON migration report.
  • Supported rewrite table plus manual-review findings for unsupported SQLAlchemy patterns.
  • Rollback checklist, manager summary, license/support terms, and buyer terms.

Example before/after

See the migration deliverable before checkout.

Illustrative output format: sample counts and validation results below are not a run on your repository. Use the linked proof artifacts for recorded evidence. You can also make changes manually using the free report and migration guides.

Free scan commands

python -m pip install "https://github.com/zippertools/sqlalchemy-14-to-20-codemod/archive/refs/tags/v0.1.2.zip"
python -m sa20_pack.cli . --report migration-report.json

If installation fails, retry from the GitHub quickstart or contact support at support@zippertools.org.

Sample report

Scan complete
supported_findings: 38
manual_review_findings: 6
files_uploaded: 0
next_step: preview deterministic rewrites

Before/after diff preview

- user = session.query(User).get(user_id)
+ user = session.get(User, user_id)

- stmt = select([User.id, User.email])
+ stmt = select(User.id, User.email)

The value is the controlled workflow: scan, preview, apply supported rewrites, review manual findings, and validate on your branch.

PatternBehavior
Query.get primary-key lookupsrewrite
select([..]) list syntaxrewrite
simple string joins/loadersrewrite
engine.execute transaction choicesmanual review

Apply output

apply output
files_changed: 4
transforms_applied: query_get, select_list_syntax, declarative_imports
manual_review_findings: 6
report_written: migration-report.json

Validation summary

validation summary
python -m compileall target_repo ... passed
pytest selected_fixture_suite ... passed
manual_review_export ... passed
overall: branch validation still required

Final manager summary

final manager summary
Supported cleanup findings: 38
Manual-review findings: 6
Next step: inspect diff, then run the buyer repo's own tests.

Use this if

  • The free scan finds repeated supported SQLAlchemy cleanup across enough files to matter.
  • You want a branch-local migration run with reviewable diffs and a structured report.
  • Your team can run typecheck, tests, or build after the migration before merging.

Public proof and fit signals

  • Public proof shows supported rewrites on real public files.
  • Fail-closed proof shows engine.execute(...) stays blocked instead of guessed.
  • The public repo remains scanner-first so a buyer can qualify fit before purchase.

Do not use this if

  • Repos whose real pain is broad Query-to-select rewriting.
  • Teams that want a full custom migration service.
  • Any workflow that expects engine.execute(...) to be auto-fixed everywhere.

How delivery works

  • Stripe Checkout handles secure payment and receipts.
  • Download your purchased ZIP after payment.
  • Runs locally; no hosted API, repo upload, or production credentials needed.
  • Run the pack on a branch, inspect the diff/report, then use your normal validation commands before merge.

Refund/support note

14-day refund review for published-scope or delivery mismatches. Support is by email; include the scanner report and checkout email so the issue can be matched to the published scope.

Support: support@zippertools.org

Related fixes

Exact-problem guides for this product

How to replace session.query(...).get(...) in SQLAlchemy 2.0Fix Query.get migrations and move identity lookups onto Session.get(...).What to do with session.query(...) during a SQLAlchemy 2.0 migrationSeparate the easy Query cleanup from the broader Query-to-select refactor work.How to fix engine.execute(...) removal in SQLAlchemy 2.0Fix engine.execute removals and OptionEngine errors without pretending the replacement is always trivial.How to clean up joinedload_all(...) during a SQLAlchemy 2.0 migrationReplace joinedload_all(...) with mapped-attribute loader options and bucket the hard cases honestly.How to replace select([..]) list syntax in SQLAlchemy 2.0Drop the legacy select([..]) wrapper and move to direct select(...) calls.How to replace string join paths during a SQLAlchemy 2.0 migrationReplace simple join("addresses") and outerjoin("orders") calls with mapped attributes when the root entity is obvious.How to replace string loader options in SQLAlchemy 2.0Replace joinedload("addresses") and similar string loader options with mapped attributes when the relationship root is obvious.How to move sqlalchemy.ext.declarative imports to sqlalchemy.ormReplace legacy declarative_base and declared_attr imports from sqlalchemy.ext.declarative.How to replace insert(..., values=...) in SQLAlchemy 2.0Move legacy insert constructor kwargs onto the statement object with .values(...).How to replace update(..., whereclause=..., values=...) in SQLAlchemy 2.0Move legacy update constructor kwargs onto the statement object with .where(...).values(...).How to replace delete(..., whereclause=...) in SQLAlchemy 2.0Move legacy delete constructor kwargs onto the statement object with .where(...).What to do about Query.from_self() removal in SQLAlchemy 2.0Treat Query.from_self() as a manual-review migration instead of pretending there is one safe automatic replacement.Why multi-hop string joins are a manual-review case in SQLAlchemy 2.0Understand why join("orders", "items") belongs in manual review instead of a guessed codemod.How to replace Query.as_scalar() with scalar_subquery() in SQLAlchemy 2.0Migrate legacy Query.subquery().as_scalar() calls to the scalar_subquery() method.How to wrap raw SQL strings in text() for SQLAlchemy 2.0Raw SQL strings now need explicit text() wrapping in SQLAlchemy 2.0 execute calls.How to adapt session.execute() result handling in SQLAlchemy 2.0Session.execute() in 2.0 returns Result objects, not lists. Use .scalars() or .all() for ORM rows.How to replace backref strings with back_populates in SQLAlchemy 2.0The string backref pattern still works but explicit back_populates is the modern approach.Fix 'OptionEngine' object has no attribute 'execute' in SQLAlchemy 2.0Fix the common OptionEngine execute error by moving execution onto a Connection or Session.Fix 'Engine' object has no attribute 'execute' in SQLAlchemy 2.0Resolve Engine.execute attribute errors without guessing transaction behavior.Fix LegacyAPIWarning: Query.get() is legacy in SQLAlchemy 2.0Replace Query.get warnings with Session.get in the safe primary-key lookup subset.Fix SQLAlchemy legacy select([..]) warningsDrop the old select list wrapper and use direct select(...) arguments.Fix joinedload_all is not defined in SQLAlchemy 2.0Replace joinedload_all usage with chained joinedload calls when the path is obvious.SQLAlchemy 2.0 migration triage checklistSort SQLAlchemy 2.0 migration work into safe codemod, manual review, and staged refactor buckets.Manual SQLAlchemy 2.0 migration vs codemodDecide when a SQLAlchemy 2.0 migration should use a deterministic codemod and when it should stay manual.