Schema Bridge: PyQt ↔ Elixir
Setup
Mix.install([
{:jason, "~> 1.4"},
{:ecto, "~> 3.10"},
{:kino, "~> 0.11.0"},
{:explorer, "~> 0.7.0"}
])
# Project setup
File.cd!("../")
Code.require_file("config/config.exs")
Schema Generator
defmodule SchemaBridge do
def generate_ecto_schema(json_schema) do
"""
defmodule #{json_schema["module_name"]} do
use Ecto.Schema
import Ecto.Changeset
schema "#{json_schema["table_name"]}" do
#{generate_fields(json_schema["fields"])}
timestamps()
end
def changeset(struct, params \\\\ %{}) do
struct
|> cast(params, #{generate_field_list(json_schema["fields"])})
|> validate_required(#{generate_required_fields(json_schema["fields"])})
end
end
"""
end
def generate_pyqt_model(json_schema) do
"""
from PyQt6.QtCore import Qt, QAbstractTableModel
from dataclasses import dataclass, field
from typing import Optional, List, Dict
from datetime import datetime
@dataclass
class #{json_schema["class_name"]}:
#{generate_python_fields(json_schema["fields"])}
class #{json_schema["class_name"]}Model(QAbstractTableModel):
def __init__(self, data=None):
super().__init__()
self._data = data or []
self._headers = #{generate_python_headers(json_schema["fields"])}
"""
end
end
Schema Validator
defmodule SchemaValidator do
def validate_schema(schema) do
with {:ok, _} <- validate_structure(schema),
{:ok, _} <- validate_types(schema),
{:ok, _} <- validate_constraints(schema) do
{:ok, schema}
end
end
end
Interactive Schema Editor
schema_input = Kino.Input.textarea("Enter JSON Schema")
form = Kino.Control.form([schema: schema_input], submit: "Generate")
Kino.listen(form, fn %{data: %{schema: schema_json}} ->
case Jason.decode(schema_json) do
{:ok, schema} ->
Kino.Layout.tabs([
"Ecto Schema": Kino.Markdown.new("```elixir\n#{SchemaBridge.generate_ecto_schema(schema)}\n```"),
"PyQt Model": Kino.Markdown.new("```python\n#{SchemaBridge.generate_pyqt_model(schema)}\n```")
])
{:error, error} ->
Kino.Markdown.new("Error: #{inspect(error)}")
end
end)