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, dagster-webserver).
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,polars,dagsteredagster-webserver - 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)
- Navegação pelos bancos e schemas do servidor — sem precisar digitar o nome do banco
- Opção de criar banco e schema no destino direto pelo fluxo interativo
- Geração automática de schemas a partir do banco de origem: lista tabelas e colunas, infere tipos, PK, FK, unique e default
- Ordenação do
main.ymlpor dependência (pais antes de filhos) - Gerenciamento automático de schedules: infere colunas de atualização incremental, cria um schedule padrão de hora em hora por tabela e um schedule para o modelo geral
- Geração de código Dagster padrão que segue a chave
schedulede cada schema (cron,mode,incremental_column,full_loadetruncate) - Comando
conduto schedulespara (re)gerar os schedules e o código Dagster de um projeto existente - 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 e usuário mudam conforme o SGBD
- Credenciais do servidor de origem (host, porta, usuário e senha) — sem precisar digitar o banco
- Teste de conexão — se falhar, escolha entre digitar novamente ou continuar mesmo assim
- Lista de bancos do servidor de origem — escolha um
- Lista de schemas do banco escolhido — escolha um
- SGBD de destino
- Credenciais de destino, com o mesmo fluxo — e com opção de criar um banco e/ou schema novo
- Como configurar os schemas: gerar automaticamente a partir do banco de origem (tabelas, colunas e tipos inferidos) ou configurar manualmente (gera os exemplos)
- Gerenciamento de schedules — pergunta se você quer gerar automaticamente o schedule de cada tabela (padrão: hora em hora) e o código Dagster correspondente
- Servidor Dagster — pergunta se você quer subir o servidor agora (
uv run dagster dev) e gera os scriptsrun_dagster.ps1/run_dagster.sh
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).
Geração automática de schemas
Depois de testar as duas conexões, o conduto pergunta como você quer configurar os schemas das tabelas:
- Gerar automaticamente: o conduto lista as tabelas do banco de origem, permite marcar/desmarcar quais incluir, lê as colunas (tipos, PK, FK, unique, default e nullable) e gera os
schemas/*.ymle omain.ymlna ordem de dependência (pais antes de filhos). - Configurar manualmente: mantém o comportamento atual e gera os três schemas de exemplo (clientes, pedidos e produtos) para você editar.
DDL para o banco de destino
Depois de gerar os schemas, o conduto ddl converte tudo em CREATE TABLE para o banco de destino. Antes de gerar, ele pergunta se você quer aplicar agora no banco de destino ou apenas gerar o DDL para aplicar depois. No conduto init (modo gerar automaticamente), a mesma pergunta aparece ao final da geração dos schemas:
# pergunta se quer aplicar agora ou só gerar
conduto ddl
# salva o DDL em um arquivo .sql (aplicação fica para depois)
conduto ddl --output ddl.sql
# aplica direto no banco de destino (cria o schema se necessário), sem perguntar
conduto ddl --apply
# apenas gera o DDL, sem perguntar
conduto ddl --no-apply
As flags --apply e --no-apply pulam a pergunta interativa (útil para scripts). O comando lê o .env (credenciais de destino), o main.yml (ordem de dependência) e os schemas/*.yml, traduzindo tipos e funções (ex.: gen_random_uuid(), clock_timestamp()) para o SGBD de destino (PostgreSQL, MySQL ou SQL Server). Por padrão roda no diretório atual; use --dir caminho/do/projeto para outro diretório.
Schedules e Dagster
Ao final do conduto init, o conduto pergunta se você quer gerenciar os schedules automaticamente. Se sim:
- Mapeia as tabelas e tenta inferir a coluna de atualização incremental (watermark): prioriza colunas como
updated_at/atualizado_em, depoiscreated_at/criado_eme, por fim, qualquer coluna temporal - Cria um schedule padrão de hora em hora (
0 * * * *) para cada tabela, gravado na chavescheduledo schema YAML — edite à vontade:
schedule:
cron: "0 * * * *"
mode: incremental # incremental (usa incremental_column) ou full
incremental_column: updated_at
full_load: false # true força uma carga completa na próxima execução
truncate: false # true limpa a tabela de destino antes de carregar
- Adiciona o schedule do modelo geral no
main.yml(executa todas as tabelas na ordem de dependência) - Gera o pacote
conduto_dagster/com os assets e schedules, além dodefinitions.pyna raiz — para rodar, é só executaruv run dagster dev - Adiciona o bloco
[tool.dagster]nopyproject.tomlapontando para as definições — odagster dev(versões recentes) exige esse bloco ou um argumento-m/-fpara localizar o código
O código Dagster lê o main.yml e os schemas/*.yml em tempo de execução: alterar a chave schedule de um schema muda o asset/schedule sem precisar regenerar nada. Tabelas com FK viram dependências de assets (pais antes de filhos).
Para regenerar depois (por exemplo, após adicionar uma tabela nova):
# na raiz do projeto
conduto schedules
# apontando para outro diretório
conduto schedules --dir caminho/do/projeto
Os valores já editados nos YAMLs são preservados na regeneração — só as chaves ausentes recebem o padrão.
Subindo o servidor Dagster
Ao final do conduto init, o conduto também pergunta se você quer subir o servidor Dagster agora e gera comandos prontos no projeto:
# na raiz do projeto
uv run dagster dev
# ou pelos scripts gerados
.\run_dagster.ps1 # Windows
./run_dagster.sh # Linux/macOS
# ou direto pelo conduto
conduto dagster
conduto dagster --dir caminho/do/projeto
O servidor abre em http://localhost:3000 — pressione Ctrl+C para encerrar. O dagster dev exige o pacote dagster-webserver; o conduto o instala junto com as demais dependências e, se faltar num projeto já existente, instala automaticamente antes de subir o servidor (uv add dagster-webserver).
Enquanto o servidor inicializa, o conduto mostra um status animado ("Aguardando o servidor Dagster iniciar...") e avisa quando ele estiver no ar — nada de tela parada sem sinal de progresso. Se o código conduto_dagster/ ainda não existir no projeto, ele é gerado na hora a partir do main.yml e dos schemas/*.yml, e o bloco [tool.dagster] é adicionado ao pyproject.toml automaticamente.
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
├── run_dagster.ps1 / run_dagster.sh # comandos para subir o Dagster
├── definitions.py # ponto de entrada do dagster dev (com schedules)
├── conduto_dagster/ # código Dagster padrão (com schedules)
│ ├── __init__.py
│ ├── etl.py
│ └── definitions.py
├── schemas/
│ ├── clientes.yml
│ ├── pedidos.yml
│ └── produtos.yml
└── ambiente uv (pyyaml, jinja2, polars, dagster, dagster-webserver)
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. O projeto é inicializado sem pastasrc/(uv init --bare) — scripts e código Dagster ficam na raiz.
.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_SCHEMA=public
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_SCHEMA=public
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
# Schedule do modelo geral (todas as tabelas, na ordem de dependência)
schedule:
cron: "0 * * * *"
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"
schedule:
cron: "0 * * * *"
mode: incremental
incremental_column: criado_em
full_load: false
truncate: false
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 --bare # sem pasta src/
uv add pyyaml jinja2 polars dagster dagster-webserver
O projeto é inicializado sem a pasta src/, pois os scripts e o código Dagster ficam na raiz. 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.env- Se você escolheu gerar automaticamente,
database/introspect.pylê tabelas e colunas do banco de origem eschemas/schemas_auto.pygera os schemas e omain.yml; caso contrário,schemas_renderrenderiza os exemplos emschemas/ - Se você optou por gerenciar schedules,
schedules/schedules_auto.pyinfere colunas de atualização incremental, grava a chaveschedulenos schemas e nomain.yml, eschedules/dagster_render.pygera o código Dagster padrão setup_uv_environmentrodauv init(se necessário) euv adddas dependências
Próximos passos
- Revise os schemas em
schemas/(na geração automática eles já refletem o banco de origem) - Revise o
.envcom as credenciais corretas de origem e destino - Revise os schedules em cada schema (
cron,mode,incremental_column,full_load,truncate) e o schedule do modelo geral nomain.yml - Suba o servidor Dagster:
uv run dagster dev,run_dagster.ps1(Windows),run_dagster.sh(Linux/macOS) ouconduto dagster— assets e schedules já vêm montados a partir dos YAMLs
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 Distributions
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.4-py3-none-any.whl.
File metadata
- Download URL: conduto-0.1.4-py3-none-any.whl
- Upload date:
- Size: 47.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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 |
01aa7b6c555b3e097c15c7de1ae960a2055e0d7d4c3863e0958762883a663fca
|
|
| MD5 |
1af10fac1e0d084e341f377b4c7eef0a
|
|
| BLAKE2b-256 |
5c265493e36f104cbd5ba32159720b9b2ef2852d20c3cfc5a511dd83e8008d54
|