Changelog
📝 Changelog – Novos Módulos e Funcionalidades¶
📚 Registry.py
– Registro Global de Modelos e Cache¶
🗂️ Estrutura Global¶
_model_registry
: armazena todas as classesModel
já geradas e disponíveis para autocomplete e reuso._model_cache
: mapeia modelos por(table_name, conn_id)
para evitar recriação redundante._query_result_cache
: cache em memória de resultados de queries, com TTL, usado emQuerySet
.
Este módulo fornece a base para funcionalidades como: - Cache de queries (com
live()
para bypass). - Reload automático de modelos. - Geração de stubs baseados em modelos carregados dinamicamente.
📦 Model_cache.py
– Persistência de Modelos em Disco¶
🔐 Criptografia e Armazenamento¶
- Implementado mecanismo de cache criptografado de modelos em
.wbmodels/
com chave Fernet salva em.wbormkey
. - Os modelos são serializados com
pickle
, criptografados e salvos com a extensão.wbm
.
📤 Funções Principais¶
save_model_to_disk(table_name, model_cls)
- Salva um modelo ORM como dicionário de atributos serializáveis (campos e relações).
try_load_model_from_disk(table_name, conn)
- Tenta carregar um modelo previamente salvo, reconstruindo a classe com
ModelMeta
, registrando no cache e módulo principal. generate_model_stub(output_path)
- Gera automaticamente o arquivo
.pyi
para autocomplete com base nos modelos registrados. - Produz anotações de tipo para editores com base em campos e nullability.
🔑 Segurança¶
- Utiliza
cryptography.fernet.Fernet
para garantir que o cache seja seguro, mesmo se exposto.
🧠 Expressions.py
– Expressões SQL Customizadas¶
📐 Expressões Declarativas¶
- Classe
Expression
permite construir expressões SQL de forma fluida e segura: - Operadores implementados:
==
,!=
,>
,<
,>=
,<=
. - Integração com valores do tipo
datetime
com conversão automática.
🔧 Funções utilitárias para consultas¶
col(name)
– cria expressão com base em nome de coluna.date(field)
– envolve campo comDATE(...)
do Informix.now()
– insere a expressãoCURRENT
.raw(expr)
– insere SQL arbitrário diretamente.format_informix_datetime(value)
– convertedatetime
oustr
para formatoDATETIME(...) YEAR TO SECOND
, suportando ISO8601 ou fallback para strings brutas.
Essas funções já estão expostas no pacote principal via
__init__.py
, permitindo:from wborm import col, now, raw
📝 Utils.py
¶
🚀 Novas Funcionalidades¶
- Persistência de modelos em disco (cache local)
- Adição da verificação de modelos armazenados via
try_load_model_from_disk()
antes de gerar novamente. -
Os modelos gerados são salvos com
save_model_to_disk()
para reutilização futura sem nova introspecção. -
Injeção automática no escopo global
-
Nova funcionalidade com
inject_globals=True
para permitir que os modelos sejam automaticamente atribuídos a variáveis globais com o nome da tabela. -
Stub de autocomplete
-
Introdução de
generate_model_stub()
após geração de modelos, preparando arquivos.pyi
para suporte a autocomplete em editores de código. -
Listagem de modelos
-
Nova função
list_models()
que permite:- Listar todos os modelos carregados do banco de dados se houver uma conexão.
- Listar modelos armazenados no cache
.wbmodels/
se não houver conexão ativa, com descriptografia viacryptography.fernet
.
-
Geração em lote de modelos
-
Nova função
generate_all_models(conn)
para introspecção automática de todas as tabelas (e opcionalmente views), com controle de verbosity e injeção em escopo. -
Acesso seguro a modelos por nome
-
Função
get_model_by_name(name)
permite acesso direto ao modelo carregado a partir do_model_registry
. -
Criação de tabelas temporárias a partir de queryset
- Adição da função
create_temp_table_from_queryset(...)
que permite gerar tabelas temporárias (TEMP TABLE
) a partir de uma consulta ORM.
🔧 Aprimoramentos¶
- Tratamento de exceções em FKs
-
Implementado
try/except
com mensagem de aviso amigável ao ignorar falhas na leitura de FKs. -
Módulo do modelo explicitamente definido
-
Atributo
__module__
dos modelos agora é definido como"wborm.core"
, garantindo rastreabilidade correta e suporte ao autocomplete. -
Registro global de modelos
-
Modelos agora também são armazenados em
_model_registry
, além do_model_cache
, permitindo recuperação nominal direta. -
Melhoria no mapeamento de nomes
-
Os nomes de variáveis e atributos agora são tratados explicitamente como
str(col["name"])
para evitar inconsistências. -
Distribuição de importações
- Organização mais clara dos
imports
, separando o uso de bibliotecas externas (cryptography
,pickle
) e módulos internos (wborm.registry
,wborm.model_cache
etc.).
🗑️ Remoções¶
- Nenhuma funcionalidade foi removida. A nova versão mantém retrocompatibilidade total, ampliando as capacidades existentes.
⚠️ Observações Técnicas¶
- Para o correto funcionamento do cache local, é necessário garantir que:
- A chave de criptografia está acessível (
get_or_create_key()
). - O diretório
.wbmodels/
esteja presente e com permissões adequadas. - A introspecção de FKs pode ser ignorada silenciosamente em caso de falhas, garantindo robustez mas ocultando erros mais sutis se não logado em detalhes.
📝 Introspect.py
¶
🚀 Melhoria Robusta na Função get_foreign_keys()
¶
🔍 Análise de Chaves Estrangeiras (FK) com Base em Índices¶
- A consulta agora utiliza
sysindexes
para identificar corretamente as colunas envolvidas nos relacionamentos, tanto no lado da chave estrangeira quanto da chave primária. - Suporte a até 16 colunas de índice (usando
part1
apart16
), permitindo detectar relacionamentos compostos com múltiplas colunas.
🧠 Correções Semânticas e de Precisão¶
- Substituição do join direto por
r.tabid = fk.tabid
para o uso dec.tabid = fk.tabid
, garantindo precisão na tabela filha (fk
). - Inclusão do filtro
idx_fk.part1 IS NOT NULL AND idx_pk.part1 IS NOT NULL
para garantir que apenas relacionamentos com colunas de índice reais sejam retornados, evitando registros corrompidos ou incompletos.
🧹 Tratamento com COALESCE
¶
- Uso de
COALESCE(..., '')
garante robustez ao comparar nomes de tabelas com possíveis valores nulos, evitando falhas silenciosas ou quebras porNULL
.
🛠️ Outros Ajustes Técnicos¶
- Indentação SQL melhorada para clareza e leitura.
- Os aliases
fk
,pk
,fc
epc
permanecem os mesmos, mas agora baseados em um cruzamento mais preciso com os índices referenciados nas constraints. - Estrutura da query refatorada para melhor manutenção futura e consistência com bancos que seguem o padrão Informix para metadados.
✅ Nenhuma alteração em introspect_table()
¶
A função introspect_table(...)
permanece inalterada entre as versões antiga e nova. Portanto:
- Sem impacto em chamadas existentes.
- Mesma estrutura de introspecção de colunas.
📝 Query.py
¶
🚀 Novas Funcionalidades¶
🧠 Cache de Resultados de Consultas¶
- Introduzido cache local de resultados (
_query_result_cache
) com TTL configurável (_cache_ttl = 60
segundos por padrão). - Nova função
live()
para desativar temporariamente o cache em uma consulta específica. - Verificação e reutilização de resultados cacheados em
all()
para otimizar desempenho.
🧾 Classe ResultSet com Métodos Avançados¶
- Nova classe
ResultSet
herda delist
e adiciona: show(tablefmt="grid")
: renderização de resultados comtabulate
, com destaque de cor (verde para consulta ao vivo, azul para cache).- Suporte a colunas dinâmicas com detecção automática ou baseadas em
select(...)
. - Remoção automática de colunas 100% vazias.
📊 Função pivot(...)
¶
- Novo método
pivot(...)
permite transformar a saída em uma visualização estilo tabela dinâmica, com indexação, colunas cruzadas e valores preenchidos. - Uso de
tabulate
, cores de terminal ANSI e performance otimizada.
🧪 Função show(...)
no QuerySet¶
- Método
show()
que simplesmente chamaall().show(...)
com suporte a formato tabular customizável.
🧩 Suporte a Subqueries via Join¶
- Método
join()
agora aceita umQuerySet
com alias definido por.as_temp_table(alias)
, permitindo joins com subqueries SQL completas.
🧪 Criação de Tabelas Temporárias Encadeada¶
- Método
create_temp_table(...)
disponível diretamente em umQuerySet
para gerar uma tabela temporária com base na query atual e retornar automaticamente o modelo associado.
🔧 Melhorias em Funcionalidades Existentes¶
filter(...)
mais poderoso-
Agora aceita expressões livres como strings (
filter("age > 30")
) e objetosColumnExpr
, além do tradicionalfilter(campo=valor)
com escaping seguro de aspas simples. -
join(...)
com cláusula ON flexível -
Agora aceita:
- Lista/tupla de colunas para
ON a.col = b.col
. - Expressão simples (
"user_id"
) assumindo igualdade padrão. - Expressão SQL customizada.
- Lista/tupla de colunas para
-
Criação explícita de instâncias
-
Método
_create_instance_from_row(...)
cria objetos com fallback direto ao__dict__
se o campo não estiver em_fields
. -
select(...)
propaga campos para oResultSet
-
Permite renderização mais precisa e ordenada de colunas.
-
Escape seguro em
count()
- Protege os valores de filtro contra SQL Injection com
str(v).replace("'", "''")
.
🗑️ Remoções / Alterações Descontinuadas¶
- A função
preload(...)
foi removida no novo código. A pré-carga de relações precisa ser reimplementada caso seja necessária. - A lógica heurística de FKs inversas em
preload(...)
(baseada emid
ou<rel>_id
) foi descontinuada. - O método
all()
agora retorna umResultSet
, em vez de uma lista simples.
🎨 Melhorias Visuais e de UX¶
- Integração com
colorama
para colorir bordas de tabelas no terminal conforme origem dos dados (cache ou vivo). - Utilização de
tabulate
com diversos formatos para facilitar leitura em CLI.
⚙️ Internals e Técnicas¶
- Inclusão de hashing (
sha256
) para cache de consultas baseado no texto SQL. - Identificação de subqueries exige
._as_temp_table_alias
definido previamente para segurança. - Compatível com
generate_model()
atualizado para modelos temporários injetáveis.
📝 Core.py
¶
🚀 Novas Funcionalidades¶
🧬 Suporte a métodos dinâmicos de QuerySet
¶
- Interceptação automática via
__getattr__
na metaclasseModelMeta
: - Permite invocar qualquer método disponível no
QuerySet
diretamente pela classe modelo, comoUser.limit(10).show()
. - Exemplo:
Model.join(...)
,Model.show()
,Model.pivot(...)
, etc., mesmo sem declarar manualmente.
📦 Criação de Tabelas Temporárias¶
- Novo método
create_temp_table()
(em dois níveis: instância e classe): - Gera automaticamente a estrutura SQL com base nos campos do modelo.
- Usa
CREATE TEMP TABLE ...
com log visual viacprint
. - Útil para joins intermediários e persistência temporária de resultados filtrados.
📊 Visualização Avançada: Model.show(...)
¶
- Exibe resultados no terminal com
tabulate
, até 50 registros por padrão (ou filtrado). - Renderiza com cores no terminal usando
colorama
: - Azul (🔵) se o modelo for proveniente de cache.
- Verde (🟢) se for carregado dinamicamente.
🔁 Pivot Dinâmico via Model.pivot(...)
¶
- Geração de tabela dinâmica (
pivot
) diretamente pelo modelo, com suporte a filtros e agregações (aggfunc="count"
por padrão).
🔍 Relações Modeladas Visivelmente: Model.describe_relations()
¶
- Lista todas as relações mapeadas automaticamente para o modelo, exibindo nome do relacionamento e tabela de destino.
🔧 Melhorias Significativas¶
- Melhoria na introspecção de campos (
ModelMeta
): -
Usa
str(k)
para garantir compatibilidade com chaves não-string (robustez com introspecção dinâmica ou subclasses especiais). -
Refinamento em
to_dict()
: -
Agora ignora atributos que começam com
_
ou que são métodos, gerando um dicionário limpo apenas com dados úteis. -
Melhoria na criação de tabelas (temporárias e fixas):
- Compactação da lógica de tipo SQL + flags
NOT NULL
ePRIMARY KEY
com.strip()
no final. - Código mais legível e reutilizável.
🗑️ Remoções / Alterações Descontinuadas¶
- 📤 Removido o método
show()
de instância -
Substituído por um
show()
de classe, mais útil e abrangente. -
📦 Método
preload()
doQuerySet
ainda referenciado, mas provavelmente obsoleto (dependência que sumiu emQuerySet
novo). - Pode ser removido futuramente se confirmado o desuso.
🎨 Melhorias de Interface e UX¶
- Saída mais bonita com
colorama
para destaque de tabelas, relações e mensagens de criação. - Mensagens informativas ao criar tabelas (
🧪 Tabela temporária criada: ...
), deletar ou atualizar.
🛠️ Técnicas e Estruturais¶
lazy_property
permanece como helper funcional, sem alterações.validate()
continua garantindo consistência e obrigatório antes de qualquer operação de persistência (add
,bulk_add
, etc.).
📝 __init__.py
¶
🚀 Novos Recursos Exportados Publicamente¶
Foram adicionados novos utilitários à API pública da biblioteca, permitindo um uso mais expressivo e direto de expressões SQL e funções auxiliares:
📐 Expressões e Funções Utilitárias¶
col
– Criação de expressões baseadas em colunas (ex:col("idade") > 18
).date
– Conversão e manipulação de valores de data.now
– Data/hora atual para uso em filtros ou inserções.raw
– Inserção de SQL bruto diretamente em expressões.format_informix_datetime
– Utilitário para formatar datas no padrão aceito pelo Informix.
Esses recursos vêm do novo módulo
expressions.py
, agora incluído como parte do pacote principal.
🧭 Exportação Explícita com __all__
¶
- Adição do bloco
__all__ = [...]
, tornando explícito o que é exportado ao usarfrom wborm import *
, melhorando: - Legibilidade e manutenção.
- Controle de namespace.
- Completude para IDEs e documentação automática.
✅ Retrocompatibilidade Mantida¶
- Todos os elementos anteriormente exportados (
Model
,Field
,generate_model
,get_model
,QuerySet
) continuam disponíveis sem alterações.