O! My Models (omymodels) - a universal Python library for:
- Generating ORM models from SQL DDL (CREATE TABLE)
- Converting models between different frameworks (Pydantic → SQLAlchemy, etc.)
Version: 1.0.0 Python: >=3.9 License: MIT
omymodels/
├── __init__.py # Public API: create_models(), convert_models()
├── from_ddl.py # Main DDL generation module
├── converter.py # Converter between model types
├── cli.py # Command line interface (omm)
├── generators.py # Router to generators
├── helpers.py # Utilities (pluralize, snake_case, etc.)
├── logic.py # Column and table generation logic
├── errors.py # Exceptions
├── types.py # Base SQL type definitions
├── plugins.py # Plugin system for custom generators
├── openapi.py # OpenAPI 3 schema conversion
│
├── generation/ # Base generator classes
│ ├── base.py # BaseGenerator abstract class
│ ├── datamodel_base.py # Base for data models (Pydantic, Dataclass)
│ └── orm_base.py # Base for ORM models (SQLAlchemy, Gino)
│
└── models/ # Generators for each model type
├── gino/ # GinoORM (async PostgreSQL)
├── pydantic/ # Pydantic v1 (validation, Optional[X])
├── pydantic_v2/ # Pydantic v2 (validation, X | None)
├── sqlalchemy/ # SQLAlchemy ORM
├── sqlalchemy_core/ # SQLAlchemy Core (Table API)
├── sqlmodel/ # SQLModel (SQLAlchemy + Pydantic)
├── dataclass/ # Python Dataclasses
├── enum/ # Python Enum
├── openapi3/ # OpenAPI 3 schema generator
├── pydal/ # PyDAL (in development)
└── tortoise/ # Tortoise ORM (in development)
Each generator contains:
core.py- ModelGenerator classtypes.py- SQL → target type mappingtemplates.py- code string templates*.jinja2- final file template
SQL DDL (Input)
│
▼
┌─────────────────────────────┐
│ DDL Parser │
│ (simple-ddl-parser) │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Normalization │
│ - prepare_data() │
│ - convert_ddl_to_models() │
│ - TableMeta objects │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Type Conversion │
│ - types.py mapping │
│ - prepare_column_type() │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Model Generator │
│ - gino / pydantic / etc. │
│ - generate_model() │
│ - create_header() │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Jinja2 Rendering │
│ - render_jinja2_template() │
└─────────────────────────────┘
│
▼
Python Code (Output)
Base generator structure:
class ModelGenerator:
def __init__(self):
self.types_mapping # SQL → target type
self.templates # Code templates
self.state # Import tracking
self.custom_types # Enum and custom types
def generate_model(table) # Generate single model
def create_header(tables) # Header with importsSQL type groups:
string_types: VARCHAR, CHAR, TEXT, STRINGinteger_types: INTEGER, INT, SERIAL, BIGINT, SMALLINTdatetime_types: DATE, TIMESTAMP, DATETIME, TIMEbool_types: BOOLEAN, BOOLfloat_types: FLOAT, DECIMAL, NUMERIC, DOUBLEjson_types: JSON, JSONB
generate_column()- complete column definitionsetup_column_attributes()- nullable, defaults, primary_keyadd_table_args()- indexes, constraints, schemaadd_reference_to_the_column()- foreign keys
models = {
"gino": gino.ModelGenerator(),
"pydantic": pydantic.ModelGenerator(),
"pydantic_v2": pydantic_v2.ModelGenerator(),
"sqlalchemy": sqlalchemy.ModelGenerator(),
"sqlalchemy_core": sqlalchemy_core.ModelGenerator(),
"sqlmodel": sqlmodel.ModelGenerator(),
"dataclass": dataclass.ModelGenerator(),
"openapi3": openapi3.ModelGenerator(),
}from omymodels import create_models, convert_models
# Generate from DDL
result = create_models(
ddl="CREATE TABLE users (...)", # or ddl_path="schema.sql"
models_type="pydantic", # gino, sqlalchemy, dataclass, etc.
dump=True, # save to file
dump_path="models.py",
singular=False, # users → User (singularize)
schema_global=True, # global schema
defaults_off=False, # without defaults
)
# Returns: {"metadata": {...}, "code": "..."}
# Convert between types
output = convert_models(
model_from="@dataclass\nclass User: ...",
models_type="sqlalchemy"
)# Basic usage
omm schema.sql
# With options
omm schema.sql -m pydantic -t models.py
# Flags:
# -m, --models_type Model type
# -t, --target Save path
# --no-dump Output to console
# --no-global-schema Schema in table_args
# --defaults-off Without default values
# -v Verbose mode| Library | Purpose |
|---|---|
| simple-ddl-parser | SQL DDL parsing |
| table-meta | Unified TableMeta structure |
| py-models-parser | Python model parsing |
| Jinja2 | Code templating |
| pydantic | Data validation |
- SQL DDL: PostgreSQL, MySQL, MS SQL dialects
- Python code: Pydantic, Dataclasses, SQLAlchemy (for conversion)
- OpenAPI 3: JSON/YAML schema definitions
| Format | Description |
|---|---|
| GinoORM | Async PostgreSQL ORM |
| Pydantic v1 | Validation and serialization (Optional[X]) |
| Pydantic v2 | Validation and serialization (X | None) |
| SQLAlchemy ORM | Classic ORM |
| SQLAlchemy Core | Table API |
| SQLModel | SQLAlchemy + Pydantic |
| Dataclasses | Built-in Python classes |
| Python Enum | Enumerations |
| OpenAPI 3 | JSON schema definitions |
- Strategy Pattern - different generators for different types
- Template Method - Jinja2 for final rendering
- Factory Pattern -
get_generator_by_type() - Pipeline - parsing → normalization → generation → rendering
- Create folder
models/[type]/ - Add
core.pywithModelGeneratorclass - Add
types.pywith type mapping - Add
templates.pywith templates - Add
[type].jinja2 - Register in
generators.py
Custom generators can be registered without forking:
from omymodels import register_generator
from omymodels.generation import BaseGenerator
class MyORMGenerator(BaseGenerator):
def generate_model(self, table, **kwargs):
...
def create_header(self, tables, **kwargs):
...
register_generator("my_orm", MyORMGenerator)Or via entry points in pyproject.toml:
[project.entry-points."omymodels.generators"]
my_orm = "my_package.generators:MyORMGenerator"TableMeta (table-meta library)
├── name: str
├── columns: List[Column]
│ ├── name: str
│ ├── type: str
│ ├── nullable: bool
│ ├── default: any
│ ├── size: int | tuple
│ ├── primary_key: bool
│ ├── unique: bool
│ └── references: Dict (FK)
├── primary_key: List[str]
├── indexes: List[Index]
├── constraints: Dict
└── table_schema: str