A developer-first CLI tool for moving data across databases, CSVs, and Google Sheets
Project description
Portl
Portl is a developer-first CLI tool for moving data across databases, CSVs, and Google Sheets. Instead of writing one-off SQL or Python scripts for every migration, Portl gives you an interactive wizard and YAML job configs you can re-run, share, and version-control.
Portl turns migrations into a repeatable, reliable system — not a grind.
Features
- Sources: Postgres, MySQL, CSV, Google Sheets.
- Interactive wizard — no need to remember 12 flags.
- YAML job specs — portable, reusable, version-controlled.
- Hooks — run scripts or APIs before/after rows or batches.
- Dry run + schema validation.
- Batch execution with retries.
Installation
pip install portl
Quickstart
1. Start a New Migration
portl init
This launches the wizard and asks questions like:
- What's your source? (Postgres/MySQL/CSV/Google Sheet)
- What's your destination?
- How do you want to map fields?
- Conflict strategy? (skip/overwrite/merge/fail)
- Any hooks before/after rows or batches?
At the end, Portl generates a YAML job file for you.
2. Example YAML Job
source:
type: csv
path: ./data/users.csv
destination:
type: postgres
host: localhost
database: mydb
table: users
conflict: overwrite
batch_size: 100
hooks:
before_batch: ./scripts/notify_start.sh
after_batch: ./scripts/notify_done.sh
3. Run the Migration
portl run jobs/users_to_pg.yaml
4. Dry Run Preview
portl run jobs/users_to_pg.yaml --dry-run
→ Shows sample rows, schema mapping, and a row count check without writing data.
Documentation
See full docs & examples at: [coming soon]
Contributing
We welcome issues, forks, and pull requests. MIT licensed.
With Portl, you'll never write the same migration script twice.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file portl-0.0.1.tar.gz.
File metadata
- Download URL: portl-0.0.1.tar.gz
- Upload date:
- Size: 4.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b2b11fe740907711f691e6bf7a87f1dd269500e4874deae3ac0eae0826ccc25
|
|
| MD5 |
5278cb9c53f73f8a9ece7195817e3715
|
|
| BLAKE2b-256 |
778398e2d352ad6866ad5d7e8e4e29ca16de02fb36c7472994a958f33abbd82d
|
Provenance
The following attestation bundles were made for portl-0.0.1.tar.gz:
Publisher:
publish.yml on hebaghazali/portl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portl-0.0.1.tar.gz -
Subject digest:
1b2b11fe740907711f691e6bf7a87f1dd269500e4874deae3ac0eae0826ccc25 - Sigstore transparency entry: 569499281
- Sigstore integration time:
-
Permalink:
hebaghazali/portl@d9426d3db2b0418ecad367daba2b8bcb05b6e32c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/hebaghazali
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d9426d3db2b0418ecad367daba2b8bcb05b6e32c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file portl-0.0.1-py3-none-any.whl.
File metadata
- Download URL: portl-0.0.1-py3-none-any.whl
- Upload date:
- Size: 4.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
431d362ca7bb385665416f056ac63364155d4ebf624e43fabbf96403f750c11f
|
|
| MD5 |
f5b84dc61cf5f9ebb018f25b8e31ceb1
|
|
| BLAKE2b-256 |
8b77496a7e4c0a192a3037683c9e7ad2b0ed667e9bc30ba55c6632e908fd9f34
|
Provenance
The following attestation bundles were made for portl-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on hebaghazali/portl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portl-0.0.1-py3-none-any.whl -
Subject digest:
431d362ca7bb385665416f056ac63364155d4ebf624e43fabbf96403f750c11f - Sigstore transparency entry: 569499287
- Sigstore integration time:
-
Permalink:
hebaghazali/portl@d9426d3db2b0418ecad367daba2b8bcb05b6e32c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/hebaghazali
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d9426d3db2b0418ecad367daba2b8bcb05b6e32c -
Trigger Event:
workflow_dispatch
-
Statement type: