# SQLAlchemy Hero
## What is SQLAlchemy Hero?
[SchemaHero](https://schemahero.io/) lets you define declarative
database schema migrations.
In Python schemas are often mapped with
[SQLAlchemy](https://www.sqlalchemy.org/) models.
`SQLAlchemy Hero` is a package to generate the declarative table YAMLs for
`SchemaHero` from your existing `SQLAlchemy` Base.
## Getting Started
In easy cases the below code is all you need to add to a cli script.
The `Base` is your `DeclarativeBase` from `SQLAlchemy` and `./out` is the
path to output the generated table schemas.
```python
from pathlib import Path
from sqlalchemy_hero.hero_database import HeroDatabase
from sqlalchemy_hero.hero_generator import HeroGenerator
from my_app.models import Base
hero_generator = HeroGenerator(
base=Base,
db_type=HeroDatabase.postgres,
namespace="hero-ns",
database="hero-db",
)
hero_generator.to_yaml_files(out_path=Path("./out"))
```
### Example with SQLAlchemy models
Let's look at an example how to use it including some example models.
There is a `Parent` and a `Child` model both
inheriting from a abstract base model with some common fields.
The goal is to generate the table YAML files for `SchemaHero`.
The `HeroGenerator` class implements the methods to extract the model.
It is initialized with your declarative base from `SQLAlchemy`,
the database type you're using (currently `postgres` and `mysql`),
the namespace where the tables should be deployed and the database name.
The `to_yaml_files` method allowes to specify the output path for the
generated YAMLs (defaults to `Path("./out")`).
```python
from pathlib import Path
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Text
from sqlalchemy import func
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy_utils import ArrowType
from sqlalchemy_hero.hero_database import HeroDatabase
from sqlalchemy_hero.hero_generator import HeroGenerator
DeclarativeBase = declarative_base()
class Base(DeclarativeBase):
__abstract__ = True
id = Column(Integer, primary_key=True)
created_on = Column(ArrowType, default=func.now())
updated_on = Column(ArrowType, default=func.now(), onupdate=func.now())
class Parent(Base):
__tablename__ = "parent"
name = Column(Text)
ss_number = Column(Integer, autoincrement=True)
children = relationship("Child")
class Child(Base):
__tablename__ = "child"
name = Column(Text, nullable=False)
description = Column(Text, nullable=False, index=True)
parent_id = Column(Integer, ForeignKey("parent.id"))
hero_generator = HeroGenerator(
base=Base,
db_type=HeroDatabase.postgres,
namespace="hero-ns",
database="hero-db",
)
hero_generator.to_yaml_files(out_path=Path("./out"))
```
### Type Overrides
The library tries to implement the most common types but it's hard to
keep up with all the possiblities for the different databases.
If you find a not yet mapped type (commonly used with `SQLAlchemy`) please
open a pull request to add it.
For custom types or quick fixes you can override the types
(the dict entries override/add to the current types).
```python
CUSTOM_TYPE_MAPPINGS = {
MyCustomType: "text", # add new type mappings
Integer: "serial", # override existing mappings
}
hero_generator = HeroGenerator(
base=Base,
db_type=HeroDatabase.postgres,
namespace="hero-ns",
database="hero-db",
db_type_override=CUSTOM_TYPE_MAPPINGS, # add the mappings on init
)
hero_generator.to_yaml_files()
```
### API Version
We try to update the default API version for `SchemaHero` to the latest.
If you wish to use another version or if we haven't updated yet it can be
specified on initializing the `HeroGenerator`.
```python
hero_generator = HeroGenerator(
base=Base,
db_type=HeroDatabase.postgres,
namespace="hero-ns",
database="hero-db",
api_version="schemas.schemahero.io/custom-version",
)
hero_generator.to_yaml_files()
```
## QA Commands
The below commands are run in the pipeline and the according checks
are expected to pass.
```bash
poetry run pytest
poetry run black .
poetry run isort .
poetry run pylint tests sqlalchemy_hero
poetry run bandit -r sqlalchemy_hero
```
Raw data
{
"_id": null,
"home_page": "https://github.com/busykoala/sqlalchemy-hero",
"name": "sqlalchemy-hero",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "SQLAlchemy,SchemaHero,GitOps,database,k8s",
"author": "Matthias Osswald",
"author_email": "info@busykoala.io",
"download_url": "https://files.pythonhosted.org/packages/57/5a/f08c8a701e6e6f95e90383e3477a16a28ef34b5b5fb7c82de3aa09fca5f1/sqlalchemy-hero-0.1.1.tar.gz",
"platform": null,
"description": "# SQLAlchemy Hero\n\n## What is SQLAlchemy Hero?\n\n[SchemaHero](https://schemahero.io/) lets you define declarative\ndatabase schema migrations.\nIn Python schemas are often mapped with\n[SQLAlchemy](https://www.sqlalchemy.org/) models.\n\n`SQLAlchemy Hero` is a package to generate the declarative table YAMLs for\n`SchemaHero` from your existing `SQLAlchemy` Base.\n\n## Getting Started\n\nIn easy cases the below code is all you need to add to a cli script.\nThe `Base` is your `DeclarativeBase` from `SQLAlchemy` and `./out` is the\npath to output the generated table schemas.\n\n```python\nfrom pathlib import Path\n\nfrom sqlalchemy_hero.hero_database import HeroDatabase\nfrom sqlalchemy_hero.hero_generator import HeroGenerator\n\nfrom my_app.models import Base\n\nhero_generator = HeroGenerator(\n base=Base,\n db_type=HeroDatabase.postgres,\n namespace=\"hero-ns\",\n database=\"hero-db\",\n)\nhero_generator.to_yaml_files(out_path=Path(\"./out\"))\n```\n\n### Example with SQLAlchemy models\n\nLet's look at an example how to use it including some example models.\nThere is a `Parent` and a `Child` model both\ninheriting from a abstract base model with some common fields.\nThe goal is to generate the table YAML files for `SchemaHero`.\n\nThe `HeroGenerator` class implements the methods to extract the model.\nIt is initialized with your declarative base from `SQLAlchemy`,\nthe database type you're using (currently `postgres` and `mysql`),\nthe namespace where the tables should be deployed and the database name.\n\nThe `to_yaml_files` method allowes to specify the output path for the\ngenerated YAMLs (defaults to `Path(\"./out\")`).\n\n```python\nfrom pathlib import Path\n\nfrom sqlalchemy import Column\nfrom sqlalchemy import ForeignKey\nfrom sqlalchemy import Integer\nfrom sqlalchemy import Text\nfrom sqlalchemy import func\nfrom sqlalchemy.orm import declarative_base\nfrom sqlalchemy.orm import relationship\nfrom sqlalchemy_utils import ArrowType\n\nfrom sqlalchemy_hero.hero_database import HeroDatabase\nfrom sqlalchemy_hero.hero_generator import HeroGenerator\n\nDeclarativeBase = declarative_base()\n\n\nclass Base(DeclarativeBase):\n __abstract__ = True\n\n id = Column(Integer, primary_key=True)\n created_on = Column(ArrowType, default=func.now())\n updated_on = Column(ArrowType, default=func.now(), onupdate=func.now())\n\n\nclass Parent(Base):\n __tablename__ = \"parent\"\n\n name = Column(Text)\n ss_number = Column(Integer, autoincrement=True)\n children = relationship(\"Child\")\n\n\nclass Child(Base):\n __tablename__ = \"child\"\n\n name = Column(Text, nullable=False)\n description = Column(Text, nullable=False, index=True)\n parent_id = Column(Integer, ForeignKey(\"parent.id\"))\n\n\nhero_generator = HeroGenerator(\n base=Base,\n db_type=HeroDatabase.postgres,\n namespace=\"hero-ns\",\n database=\"hero-db\",\n)\nhero_generator.to_yaml_files(out_path=Path(\"./out\"))\n```\n\n### Type Overrides\n\nThe library tries to implement the most common types but it's hard to\nkeep up with all the possiblities for the different databases.\nIf you find a not yet mapped type (commonly used with `SQLAlchemy`) please\nopen a pull request to add it.\n\nFor custom types or quick fixes you can override the types\n(the dict entries override/add to the current types).\n\n```python\nCUSTOM_TYPE_MAPPINGS = {\n MyCustomType: \"text\", # add new type mappings\n Integer: \"serial\", # override existing mappings\n}\n\nhero_generator = HeroGenerator(\n base=Base,\n db_type=HeroDatabase.postgres,\n namespace=\"hero-ns\",\n database=\"hero-db\",\n db_type_override=CUSTOM_TYPE_MAPPINGS, # add the mappings on init\n)\nhero_generator.to_yaml_files()\n```\n\n### API Version\n\nWe try to update the default API version for `SchemaHero` to the latest.\nIf you wish to use another version or if we haven't updated yet it can be\nspecified on initializing the `HeroGenerator`.\n\n```python\nhero_generator = HeroGenerator(\n base=Base,\n db_type=HeroDatabase.postgres,\n namespace=\"hero-ns\",\n database=\"hero-db\",\n api_version=\"schemas.schemahero.io/custom-version\",\n)\nhero_generator.to_yaml_files()\n```\n\n## QA Commands\n\nThe below commands are run in the pipeline and the according checks\nare expected to pass.\n\n```bash\npoetry run pytest\npoetry run black .\npoetry run isort .\npoetry run pylint tests sqlalchemy_hero\npoetry run bandit -r sqlalchemy_hero\n```\n",
"bugtrack_url": null,
"license": "GPL-3.0-or-later",
"summary": "SchemaHero table generator from SQLAlchemy models.",
"version": "0.1.1",
"split_keywords": [
"sqlalchemy",
"schemahero",
"gitops",
"database",
"k8s"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "dd5a609b12534438d5add7ccac96de7b8b7140686eda2c20ee06d002a2b3e5d7",
"md5": "6f545ff9b9f69c2e2b9e560ff77969f0",
"sha256": "c07cc4729c6976e9b59d5310c5ae97683b688ad8ddcecefb87538d349bd763e2"
},
"downloads": -1,
"filename": "sqlalchemy_hero-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6f545ff9b9f69c2e2b9e560ff77969f0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 20350,
"upload_time": "2023-01-02T20:17:44",
"upload_time_iso_8601": "2023-01-02T20:17:44.095684Z",
"url": "https://files.pythonhosted.org/packages/dd/5a/609b12534438d5add7ccac96de7b8b7140686eda2c20ee06d002a2b3e5d7/sqlalchemy_hero-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "575af08c8a701e6e6f95e90383e3477a16a28ef34b5b5fb7c82de3aa09fca5f1",
"md5": "679e8385843e4352ae2b830fe2b5ea87",
"sha256": "b58240aae43a4bcc030f16ded50f995f6aef4004cbb50668495688455e974a6b"
},
"downloads": -1,
"filename": "sqlalchemy-hero-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "679e8385843e4352ae2b830fe2b5ea87",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 19556,
"upload_time": "2023-01-02T20:17:42",
"upload_time_iso_8601": "2023-01-02T20:17:42.170081Z",
"url": "https://files.pythonhosted.org/packages/57/5a/f08c8a701e6e6f95e90383e3477a16a28ef34b5b5fb7c82de3aa09fca5f1/sqlalchemy-hero-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-01-02 20:17:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "busykoala",
"github_project": "sqlalchemy-hero",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sqlalchemy-hero"
}