conduto
O duto que leva seus dados da origem ao destino.
CLI para criar projetos de migração/ELT de dados: gera o .env com as credenciais dos bancos, o manifesto main.yml, os schemas YAML das tabelas e configura o ambiente com uv (pyyaml, jinja2, polars, dagster).
Repositório: github.com/joaopedrozg/conduto
Funcionalidades
- Scaffold completo de projeto ELT em um único comando
- Fluxo interativo para configurar bancos de origem e destino (PostgreSQL, MySQL, SQL Server)
- Geração do
.envcom as credenciais das duas pontas do duto - Manifesto
main.ymlcom a ordem de dependência das tabelas - Schemas YAML de exemplo (clientes, pedidos e produtos) com PK, FK,
uniqueedefault - Ambiente Python gerenciado por
uvcompyyaml,jinja2,polarsedagster - Adapta-se automaticamente a um projeto uv existente (gera direto no projeto atual, sem subpasta nem
uv init) - Adapters de conexão com defaults por SGBD (porta, banco e usuário)
- Teste de conexão antes de gerar o projeto (com opção de digitar novamente ou seguir mesmo assim)
- Credenciais visíveis no prompt durante o preenchimento — só vão para o
.env - Instalação da lib oficial do SGBD escolhido (
psycopg[binary],pymysql,pyodbc) - Download/instalação automática do ODBC Driver for SQL Server (Windows, Linux e macOS)
- Feedback visual com
richequestionary
Instalação
pip install conduto
Ou, para usar sem sujar o ambiente atual:
uv tool install conduto
Uso
Crie um novo projeto de migração:
conduto init meu_projeto
O comando pergunta interativamente:
- SGBD de origem (PostgreSQL, MySQL ou SQL Server) — os defaults de porta, banco e usuário mudam conforme o SGBD
- Credenciais de origem, digitadas de forma visível (só vão para o
.env) - Teste de conexão de origem — se falhar, escolha entre digitar novamente ou continuar mesmo assim
- SGBD de destino
- Credenciais de destino, com o mesmo fluxo de teste
Dentro de um projeto uv? Se o diretório atual já tem pyproject.toml (por exemplo, após uv add conduto), o conduto se adapta: gera .env, main.yml e schemas/ direto no projeto atual e adiciona só as dependências que faltam — sem criar subpasta nem rodar uv init. Dentro de um projeto uv? Se o diretório atual já tem pyproject.toml (por exemplo, após uv add conduto), o conduto se adapta: gera .env, main.yml e schemas/ direto no projeto atual e adiciona só as dependências que faltam — sem criar subpasta nem rodar uv init. Nesse caso, use uv run conduto init (o nome do projeto vira opcional).
Driver ODBC do SQL Server
O pyodbc precisa do driver nativo instalado no sistema. Se a conexão com SQL Server falhar por falta de driver, o conduto init oferece a opção Instalar driver automaticamente. As credenciais já digitadas ficam guardadas só em memória e, depois da instalação, o teste de conexão é reexecutado sozinho — você não precisa digitá-las novamente. Também dá para instalar direto, sem passar pelo fluxo interativo:
conduto install-sqlserver-driver
Esse comando funciona em Windows (winget ou MSI), Linux (apt) e macOS (Homebrew). No Windows, existe ainda um script standalone que baixa o instalador oficial — útil para instalação offline ou para automatizar fora do conduto:
Durante a instalação no Windows, se o terminal não estiver como administrador, o conduto abre a janela de permissão (UAC) na frente para você confirmar. Se houver um reinício pendente no sistema, a instalação é bloqueada com um aviso claro até você reiniciar o Windows. O download e a instalação rodam em segundo plano (sem abrir janela do PowerShell) — só a confirmação do UAC aparece.
# só baixa o MSI
.\scripts\install-sqlserver-odbc.ps1 -DownloadOnly -OutFile .\msodbcsql18.msi
# baixa e instala (winget ou MSI; se precisar de administrador, o UAC abre na frente)
.\scripts\install-sqlserver-odbc.ps1
Versões suportadas: 18 (padrão) e 17 (-Version 17). Documentação oficial: Download ODBC Driver for SQL Server.
O que é gerado
meu_projeto/
├── .env
├── main.yml
├── schemas/
│ ├── clientes.yml
│ ├── pedidos.yml
│ └── produtos.yml
└── ambiente uv (pyyaml, jinja2, polars, dagster)
Fora de um projeto uv, essa estrutura é criada dentro de
meu_projeto/. Dentro de um projeto uv já existente, os arquivos são gerados no diretório atual.
.env — credenciais
Guarda as credenciais de origem e destino em variáveis DB_ORIGEM_* e DB_DESTINO_*:
DB_ORIGEM_TYPE=postgresql
DB_ORIGEM_HOST=localhost
DB_ORIGEM_PORT=5432
DB_ORIGEM_NAME=postgres
DB_ORIGEM_USER=postgres
DB_ORIGEM_PASSWORD=postgres
DB_DESTINO_TYPE=postgresql
DB_DESTINO_HOST=localhost
DB_DESTINO_PORT=5432
DB_DESTINO_NAME=postgres
DB_DESTINO_USER=postgres
DB_DESTINO_PASSWORD=postgres
Importante: o
.envcontém credenciais e não deve ser versionado.
main.yml — manifesto
Define a versão do projeto e a lista de schemas na ordem correta de dependência:
version: "1.0"
project: meu_projeto
tables:
- path: "schemas/clientes.yml"
- path: "schemas/pedidos.yml"
- path: "schemas/produtos.yml"
schemas/*.yml — tabelas
Schemas YAML que descrevem as tabelas: tipos, chave primária, foreign keys, unique e default.
table: clientes
schema: public
description: "Tabela de cadastro de clientes"
columns:
- name: id
type: integer
primary_key: true
nullable: false
- name: nome
type: varchar(255)
nullable: false
Os três exemplos cobrem padrões comuns de modelagem:
| Schema | O que demonstra |
|---|---|
clientes.yml |
chave primária, coluna unique e default com CURRENT_TIMESTAMP |
pedidos.yml |
chave estrangeira com foreign_key: clientes(id) |
produtos.yml |
tipos numeric e boolean, colunas opcionais (nullable: true) |
Ambiente uv
Se ainda não existir pyproject.toml, o conduto inicializa o projeto e instala as dependências do pipeline:
uv init --no-readme
uv add pyyaml jinja2 polars dagster
E também a lib oficial do SGBD escolhido: psycopg[binary] (PostgreSQL), pymysql (MySQL) ou pyodbc (SQL Server).
Como funciona
cli.pyfaz as perguntas de origem e destino e monta o contextoenv_renderrenderiza o template do.envschemas_renderrenderiza omain.ymle os schemas emschemas/setup_uv_environmentrodauv init(se necessário) euv adddas dependências
Próximos passos
- Ajuste os schemas em
schemas/às suas tabelas reais - Revise o
.envcom as credenciais corretas de origem e destino - Escreva suas definições Dagster (assets/jobs) dentro do projeto
- Rode e itere com
uv run dagster dev(o Dagster já vem instalado)
Desenvolvimento
uv sync
uv build
uv publish
Licença
MIT
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 conduto-0.1.3.tar.gz.
File metadata
- Download URL: conduto-0.1.3.tar.gz
- Upload date:
- Size: 18.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f208d171a58945eaa686876b0f1b4c4ab55139b25c14feafda11ef90f060f3b
|
|
| MD5 |
4c4f1d1de6e7dbe2565b4f2e72892e10
|
|
| BLAKE2b-256 |
5e400752bead51af012d7b7219070d0fe2e32aecd3c337794c8e14559276447d
|
File details
Details for the file conduto-0.1.3-py3-none-any.whl.
File metadata
- Download URL: conduto-0.1.3-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22ac654b12c0550836d52ff69fa60392e88bd80e79aceeb80bb71ac5531ef19a
|
|
| MD5 |
892d75a2e11ca3d67d9f20a7f2739b17
|
|
| BLAKE2b-256 |
59a5732d95583eabab2aa8b0ca45da8a4fe6ac3b1a6ef60e77c189bdfdaa46b6
|