Skip to content

Commit b91708d

Browse files
authored
feat: add alembic configuration (#220)
1 parent 2176d5f commit b91708d

File tree

6 files changed

+338
-0
lines changed

6 files changed

+338
-0
lines changed

alembic.ini

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# A generic, single database configuration.
2+
3+
[alembic]
4+
# path to migration scripts
5+
# script_location = alembic
6+
script_location = app\\database\\alembic
7+
8+
# template used to generate migration files
9+
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
10+
11+
# timezone to use when rendering the date
12+
# within the migration file as well as the filename.
13+
# string value is passed to dateutil.tz.gettz()
14+
# leave blank for localtime
15+
# timezone =
16+
17+
# max length of characters to apply to the
18+
# "slug" field
19+
# truncate_slug_length = 40
20+
21+
# set to 'true' to run the environment during
22+
# the 'revision' command, regardless of autogenerate
23+
# revision_environment = false
24+
25+
# set to 'true' to allow .pyc and .pyo files without
26+
# a source .py file to be detected as revisions in the
27+
# versions/ directory
28+
# sourceless = false
29+
30+
# version location specification; this defaults
31+
# to alembic/versions. When using multiple version
32+
# directories, initial revisions must be specified with --version-path
33+
# version_locations = %(here)s/bar %(here)s/bat alembic/versions
34+
35+
# the output encoding used when revision files
36+
# are written from script.py.mako
37+
# output_encoding = utf-8
38+
39+
# sqlalchemy.url = driver://user:pass@localhost/dbname
40+
41+
42+
[post_write_hooks]
43+
# post_write_hooks defines scripts or Python functions that are run
44+
# on newly generated revision scripts. See the documentation for further
45+
# detail and examples
46+
47+
# format using "black" - use the console_scripts runner, against the "black" entrypoint
48+
# hooks=black
49+
# black.type=console_scripts
50+
# black.entrypoint=black
51+
# black.options=-l 79
52+
53+
# Logging configuration
54+
[loggers]
55+
keys = root,sqlalchemy,alembic
56+
57+
[handlers]
58+
keys = console
59+
60+
[formatters]
61+
keys = generic
62+
63+
[logger_root]
64+
level = WARN
65+
handlers = console
66+
qualname =
67+
68+
[logger_sqlalchemy]
69+
level = WARN
70+
handlers =
71+
qualname = sqlalchemy.engine
72+
73+
[logger_alembic]
74+
level = INFO
75+
handlers =
76+
qualname = alembic
77+
78+
[handler_console]
79+
class = StreamHandler
80+
args = (sys.stderr,)
81+
level = NOTSET
82+
formatter = generic
83+
84+
[formatter_generic]
85+
format = %(levelname)-5.5s [%(name)s] %(message)s
86+
datefmt = %H:%M:%S

app/database/alembic/README

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Generic single-database configuration.
2+
3+
# following command will run all migration script and bring it to latest version
4+
alembic upgrade head
5+
6+
# If we like to incrementally upgrade and check for some errors
7+
alembic upgrade +1
8+
9+
# To undo last migration
10+
alembic downgrade -1
11+
12+
# To get more information
13+
alembic current
14+
alembic history - verbose

app/database/alembic/__init__.py

Whitespace-only changes.

app/database/alembic/env.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from logging.config import fileConfig
2+
import os
3+
4+
from alembic import context
5+
from sqlalchemy import create_engine
6+
7+
from app import config as app_config
8+
from app.database.models import Base
9+
10+
11+
SQLALCHEMY_DATABASE_URL = os.getenv(
12+
"DATABASE_CONNECTION_STRING", app_config.DEVELOPMENT_DATABASE_STRING)
13+
14+
# this is the Alembic Config object, which provides
15+
# access to the values within the .ini file in use.
16+
config = context.config
17+
18+
# Interpret the config file for Python logging.
19+
# This line sets up loggers basically.
20+
fileConfig(config.config_file_name, disable_existing_loggers=False)
21+
22+
# add your model's MetaData object here
23+
# for 'autogenerate' support
24+
target_metadata = Base.metadata
25+
26+
27+
# other values from the config, defined by the needs of env.py,
28+
# can be acquired:
29+
# my_important_option = config.get_main_option("my_important_option")
30+
# ... etc.
31+
32+
33+
def run_migrations_offline():
34+
"""Run migrations in 'offline' mode.
35+
36+
This configures the context with just a URL
37+
and not an Engine, though an Engine is acceptable
38+
here as well. By skipping the Engine creation
39+
we don't even need a DBAPI to be available.
40+
41+
Calls to context.execute() here emit the given string to the
42+
script output.
43+
44+
"""
45+
url = SQLALCHEMY_DATABASE_URL
46+
context.configure(
47+
url=url,
48+
target_metadata=target_metadata,
49+
literal_binds=True,
50+
dialect_opts={"paramstyle": "named"},
51+
)
52+
53+
with context.begin_transaction():
54+
context.run_migrations()
55+
56+
57+
def run_migrations_online():
58+
"""Run migrations in 'online' mode.
59+
60+
In this scenario we need to create an Engine
61+
and associate a connection with the context.
62+
63+
"""
64+
65+
connectable = create_engine(SQLALCHEMY_DATABASE_URL)
66+
67+
with connectable.connect() as connection:
68+
context.configure(
69+
connection=connection, target_metadata=target_metadata,
70+
)
71+
72+
with context.begin_transaction():
73+
context.run_migrations()
74+
75+
76+
if context.is_offline_mode():
77+
run_migrations_offline()
78+
else:
79+
run_migrations_online()

app/database/alembic/script.py.mako

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""${message}
2+
3+
Revision ID: ${up_revision}
4+
Revises: ${down_revision | comma,n}
5+
Create Date: ${create_date}
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
${imports if imports else ""}
11+
12+
# revision identifiers, used by Alembic.
13+
revision = ${repr(up_revision)}
14+
down_revision = ${repr(down_revision)}
15+
branch_labels = ${repr(branch_labels)}
16+
depends_on = ${repr(depends_on)}
17+
18+
19+
def upgrade():
20+
${upgrades if upgrades else "pass"}
21+
22+
23+
def downgrade():
24+
${downgrades if downgrades else "pass"}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""empty message
2+
3+
Revision ID: 91b42971b0df
4+
Revises:
5+
Create Date: 2021-02-06 16:15:07.861957
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects import sqlite
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '91b42971b0df'
14+
down_revision = None
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.drop_index('ix_categories_id', table_name='categories')
22+
op.drop_table('categories')
23+
op.drop_index('ix_invitations_id', table_name='invitations')
24+
op.drop_table('invitations')
25+
op.drop_index('ix_users_id', table_name='users')
26+
op.drop_table('users')
27+
op.drop_index('ix_quotes_id', table_name='quotes')
28+
op.drop_table('quotes')
29+
op.drop_index('ix_wikipedia_events_id', table_name='wikipedia_events')
30+
op.drop_table('wikipedia_events')
31+
op.drop_index('ix_zodiac-signs_id', table_name='zodiac-signs')
32+
op.drop_table('zodiac-signs')
33+
op.drop_index('ix_events_id', table_name='events')
34+
op.drop_table('events')
35+
op.drop_index('ix_user_event_id', table_name='user_event')
36+
op.drop_table('user_event')
37+
# ### end Alembic commands ###
38+
39+
40+
def downgrade():
41+
# ### commands auto generated by Alembic - please adjust! ###
42+
op.create_table('user_event',
43+
sa.Column('id', sa.INTEGER(), nullable=False),
44+
sa.Column('user_id', sa.INTEGER(), nullable=True),
45+
sa.Column('event_id', sa.INTEGER(), nullable=True),
46+
sa.ForeignKeyConstraint(['event_id'], ['events.id'], ),
47+
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
48+
sa.PrimaryKeyConstraint('id')
49+
)
50+
op.create_index('ix_user_event_id', 'user_event', ['id'], unique=False)
51+
op.create_table('events',
52+
sa.Column('id', sa.INTEGER(), nullable=False),
53+
sa.Column('title', sa.VARCHAR(), nullable=False),
54+
sa.Column('start', sa.DATETIME(), nullable=False),
55+
sa.Column('end', sa.DATETIME(), nullable=False),
56+
sa.Column('content', sa.VARCHAR(), nullable=True),
57+
sa.Column('location', sa.VARCHAR(), nullable=True),
58+
sa.Column('color', sa.VARCHAR(), nullable=True),
59+
sa.Column('owner_id', sa.INTEGER(), nullable=True),
60+
sa.Column('category_id', sa.INTEGER(), nullable=True),
61+
sa.ForeignKeyConstraint(
62+
['category_id'], ['categories.id'], ),
63+
sa.ForeignKeyConstraint(['owner_id'], ['users.id'], ),
64+
sa.PrimaryKeyConstraint('id')
65+
)
66+
op.create_index('ix_events_id', 'events', ['id'], unique=False)
67+
op.create_table('zodiac-signs',
68+
sa.Column('id', sa.INTEGER(), nullable=False),
69+
sa.Column('name', sa.VARCHAR(), nullable=False),
70+
sa.Column('start_month', sa.INTEGER(), nullable=False),
71+
sa.Column('start_day_in_month',
72+
sa.INTEGER(), nullable=False),
73+
sa.Column('end_month', sa.INTEGER(), nullable=False),
74+
sa.Column('end_day_in_month',
75+
sa.INTEGER(), nullable=False),
76+
sa.PrimaryKeyConstraint('id')
77+
)
78+
op.create_index('ix_zodiac-signs_id', 'zodiac-signs', ['id'], unique=False)
79+
op.create_table('wikipedia_events',
80+
sa.Column('id', sa.INTEGER(), nullable=False),
81+
sa.Column('date_', sa.VARCHAR(), nullable=False),
82+
sa.Column('wikipedia', sa.VARCHAR(), nullable=False),
83+
sa.Column('events', sqlite.JSON(), nullable=True),
84+
sa.Column('date_inserted', sa.DATETIME(), nullable=True),
85+
sa.PrimaryKeyConstraint('id')
86+
)
87+
op.create_index('ix_wikipedia_events_id',
88+
'wikipedia_events', ['id'], unique=False)
89+
op.create_table('quotes',
90+
sa.Column('id', sa.INTEGER(), nullable=False),
91+
sa.Column('text', sa.VARCHAR(), nullable=False),
92+
sa.Column('author', sa.VARCHAR(), nullable=True),
93+
sa.PrimaryKeyConstraint('id')
94+
)
95+
op.create_index('ix_quotes_id', 'quotes', ['id'], unique=False)
96+
op.create_table('users',
97+
sa.Column('id', sa.INTEGER(), nullable=False),
98+
sa.Column('username', sa.VARCHAR(), nullable=False),
99+
sa.Column('email', sa.VARCHAR(), nullable=False),
100+
sa.Column('password', sa.VARCHAR(), nullable=False),
101+
sa.Column('full_name', sa.VARCHAR(), nullable=True),
102+
sa.Column('language', sa.VARCHAR(), nullable=True),
103+
sa.Column('description', sa.VARCHAR(), nullable=True),
104+
sa.Column('avatar', sa.VARCHAR(), nullable=True),
105+
sa.Column('telegram_id', sa.VARCHAR(), nullable=True),
106+
sa.Column('is_active', sa.BOOLEAN(), nullable=True),
107+
sa.CheckConstraint('is_active IN (0, 1)'),
108+
sa.PrimaryKeyConstraint('id'),
109+
sa.UniqueConstraint('email'),
110+
sa.UniqueConstraint('telegram_id'),
111+
sa.UniqueConstraint('username')
112+
)
113+
op.create_index('ix_users_id', 'users', ['id'], unique=False)
114+
op.create_table('invitations',
115+
sa.Column('id', sa.INTEGER(), nullable=False),
116+
sa.Column('status', sa.VARCHAR(), nullable=False),
117+
sa.Column('recipient_id', sa.INTEGER(), nullable=True),
118+
sa.Column('event_id', sa.INTEGER(), nullable=True),
119+
sa.Column('creation', sa.DATETIME(), nullable=True),
120+
sa.ForeignKeyConstraint(['event_id'], ['events.id'], ),
121+
sa.ForeignKeyConstraint(['recipient_id'], ['users.id'], ),
122+
sa.PrimaryKeyConstraint('id')
123+
)
124+
op.create_index('ix_invitations_id', 'invitations', ['id'], unique=False)
125+
op.create_table('categories',
126+
sa.Column('id', sa.INTEGER(), nullable=False),
127+
sa.Column('name', sa.VARCHAR(), nullable=False),
128+
sa.Column('color', sa.VARCHAR(), nullable=False),
129+
sa.Column('user_id', sa.INTEGER(), nullable=False),
130+
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
131+
sa.PrimaryKeyConstraint('id'),
132+
sa.UniqueConstraint('user_id', 'name', 'color')
133+
)
134+
op.create_index('ix_categories_id', 'categories', ['id'], unique=False)
135+
# ### end Alembic commands ###

0 commit comments

Comments
 (0)