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