@ -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 |