@ -0,0 +1,74 @@ | |||||
# A generic, single database configuration. | |||||
[alembic] | |||||
# path to migration scripts | |||||
script_location = alembic | |||||
# template used to generate migration files | |||||
# file_template = %%(rev)s_%%(slug)s | |||||
# timezone to use when rendering the date | |||||
# within the migration file as well as the filename. | |||||
# string value is passed to dateutil.tz.gettz() | |||||
# leave blank for localtime | |||||
# timezone = | |||||
# max length of characters to apply to the | |||||
# "slug" field | |||||
# truncate_slug_length = 40 | |||||
# set to 'true' to run the environment during | |||||
# the 'revision' command, regardless of autogenerate | |||||
# revision_environment = false | |||||
# set to 'true' to allow .pyc and .pyo files without | |||||
# a source .py file to be detected as revisions in the | |||||
# versions/ directory | |||||
# sourceless = false | |||||
# version location specification; this defaults | |||||
# to alembic/versions. When using multiple version | |||||
# directories, initial revisions must be specified with --version-path | |||||
# version_locations = %(here)s/bar %(here)s/bat alembic/versions | |||||
# the output encoding used when revision files | |||||
# are written from script.py.mako | |||||
# output_encoding = utf-8 | |||||
sqlalchemy.url = driver://user:pass@localhost/dbname | |||||
# Logging configuration | |||||
[loggers] | |||||
keys = root,sqlalchemy,alembic | |||||
[handlers] | |||||
keys = console | |||||
[formatters] | |||||
keys = generic | |||||
[logger_root] | |||||
level = WARN | |||||
handlers = console | |||||
qualname = | |||||
[logger_sqlalchemy] | |||||
level = WARN | |||||
handlers = | |||||
qualname = sqlalchemy.engine | |||||
[logger_alembic] | |||||
level = INFO | |||||
handlers = | |||||
qualname = alembic | |||||
[handler_console] | |||||
class = StreamHandler | |||||
args = (sys.stderr,) | |||||
level = NOTSET | |||||
formatter = generic | |||||
[formatter_generic] | |||||
format = %(levelname)-5.5s [%(name)s] %(message)s | |||||
datefmt = %H:%M:%S |
@ -0,0 +1 @@ | |||||
Generic single-database configuration. |
@ -0,0 +1,76 @@ | |||||
from logging.config import fileConfig | |||||
from sqlalchemy import engine_from_config | |||||
from sqlalchemy import pool | |||||
from alembic import context | |||||
# this is the Alembic Config object, which provides | |||||
# access to the values within the .ini file in use. | |||||
config = context.config | |||||
# Interpret the config file for Python logging. | |||||
# This line sets up loggers basically. | |||||
fileConfig(config.config_file_name) | |||||
# The following is custom to get migration autogenerating working | |||||
import sys, os | |||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) | |||||
from config import Config as my_config | |||||
from app import database | |||||
config.set_main_option("sqlalchemy.url", my_config.SQLALCHEMY_DATABASE_URI) | |||||
target_metadata = database.Base.metadata | |||||
# target_metadata = None | |||||
def run_migrations_offline(): | |||||
"""Run migrations in 'offline' mode. | |||||
This configures the context with just a URL | |||||
and not an Engine, though an Engine is acceptable | |||||
here as well. By skipping the Engine creation | |||||
we don't even need a DBAPI to be available. | |||||
Calls to context.execute() here emit the given string to the | |||||
script output. | |||||
""" | |||||
url = config.get_main_option("sqlalchemy.url") | |||||
context.configure( | |||||
url=url, target_metadata=target_metadata, literal_binds=True | |||||
) | |||||
with context.begin_transaction(): | |||||
context.run_migrations() | |||||
def run_migrations_online(): | |||||
"""Run migrations in 'online' mode. | |||||
In this scenario we need to create an Engine | |||||
and associate a connection with the context. | |||||
""" | |||||
connectable = engine_from_config( | |||||
config.get_section(config.config_ini_section), | |||||
prefix="sqlalchemy.", | |||||
poolclass=pool.NullPool, | |||||
) | |||||
with connectable.connect() as connection: | |||||
context.configure( | |||||
connection=connection, target_metadata=target_metadata | |||||
) | |||||
with context.begin_transaction(): | |||||
context.run_migrations() | |||||
if context.is_offline_mode(): | |||||
run_migrations_offline() | |||||
else: | |||||
run_migrations_online() |
@ -0,0 +1,24 @@ | |||||
"""${message} | |||||
Revision ID: ${up_revision} | |||||
Revises: ${down_revision | comma,n} | |||||
Create Date: ${create_date} | |||||
""" | |||||
from alembic import op | |||||
import sqlalchemy as sa | |||||
${imports if imports else ""} | |||||
# revision identifiers, used by Alembic. | |||||
revision = ${repr(up_revision)} | |||||
down_revision = ${repr(down_revision)} | |||||
branch_labels = ${repr(branch_labels)} | |||||
depends_on = ${repr(depends_on)} | |||||
def upgrade(): | |||||
${upgrades if upgrades else "pass"} | |||||
def downgrade(): | |||||
${downgrades if downgrades else "pass"} |
@ -0,0 +1,54 @@ | |||||
"""Adding users and items tables | |||||
Revision ID: 4fe3d42f09bc | |||||
Revises: b00a3ca977cc | |||||
Create Date: 2019-07-02 19:13:32.182089 | |||||
""" | |||||
from alembic import op | |||||
import sqlalchemy as sa | |||||
# revision identifiers, used by Alembic. | |||||
revision = '4fe3d42f09bc' | |||||
down_revision = 'b00a3ca977cc' | |||||
branch_labels = None | |||||
depends_on = None | |||||
def upgrade(): | |||||
# ### commands auto generated by Alembic - please adjust! ### | |||||
op.drop_index('ix_users_email', table_name='users') | |||||
op.drop_index('ix_users_id', table_name='users') | |||||
op.drop_table('users') | |||||
op.drop_index('ix_items_description', table_name='items') | |||||
op.drop_index('ix_items_id', table_name='items') | |||||
op.drop_index('ix_items_title', table_name='items') | |||||
op.drop_table('items') | |||||
# ### end Alembic commands ### | |||||
def downgrade(): | |||||
# ### commands auto generated by Alembic - please adjust! ### | |||||
op.create_table('items', | |||||
sa.Column('id', sa.INTEGER(), nullable=False), | |||||
sa.Column('title', sa.VARCHAR(), nullable=True), | |||||
sa.Column('description', sa.VARCHAR(), nullable=True), | |||||
sa.Column('owner_id', sa.INTEGER(), nullable=True), | |||||
sa.ForeignKeyConstraint(['owner_id'], ['users.id'], ), | |||||
sa.PrimaryKeyConstraint('id') | |||||
) | |||||
op.create_index('ix_items_title', 'items', ['title'], unique=False) | |||||
op.create_index('ix_items_id', 'items', ['id'], unique=False) | |||||
op.create_index('ix_items_description', 'items', ['description'], unique=False) | |||||
op.create_table('users', | |||||
sa.Column('id', sa.INTEGER(), nullable=False), | |||||
sa.Column('email', sa.VARCHAR(), nullable=True), | |||||
sa.Column('hashed_password', sa.VARCHAR(), nullable=True), | |||||
sa.Column('is_active', sa.BOOLEAN(), nullable=True), | |||||
sa.CheckConstraint('is_active IN (0, 1)'), | |||||
sa.PrimaryKeyConstraint('id') | |||||
) | |||||
op.create_index('ix_users_id', 'users', ['id'], unique=False) | |||||
op.create_index('ix_users_email', 'users', ['email'], unique=1) | |||||
# ### end Alembic commands ### |
@ -0,0 +1,24 @@ | |||||
"""baseline | |||||
Revision ID: b00a3ca977cc | |||||
Revises: | |||||
Create Date: 2019-07-02 18:51:54.019630 | |||||
""" | |||||
from alembic import op | |||||
import sqlalchemy as sa | |||||
# revision identifiers, used by Alembic. | |||||
revision = 'b00a3ca977cc' | |||||
down_revision = None | |||||
branch_labels = None | |||||
depends_on = None | |||||
def upgrade(): | |||||
pass | |||||
def downgrade(): | |||||
pass |
@ -0,0 +1,9 @@ | |||||
import os | |||||
class Config(): | |||||
BASEDIR = os.path.abspath(os.path.dirname(__file__)) | |||||
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL") or "sqlite:///{}".format( | |||||
os.path.join(BASEDIR, "test.db") | |||||
) | |||||
SQLALCHEMY_TRACK_MODIFICATIONS = False |