Skip to content

Commit 152e547

Browse files
committed
Add flask-Migrate + alembic for automated database migrations.
Update some dependencies to their latest version. Make executable scripts executable (chmod +x).
1 parent 740be1a commit 152e547

12 files changed

+194
-16
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@
7878
- Set up `sync_es.py` as a service and run it, preferably as the system/root
7979
- Make sure `sync_es.py` runs within venv with the right dependencies
8080

81+
## Database migrations
82+
- Uses [flask-Migrate](https://flask-migrate.readthedocs.io/)
83+
- Run `./db_migrate.py db migrate` to generate the migration script after database model changes.
84+
- Take a look at the result in `migrations/versions/...` to make sure nothing went wrong.
85+
- Run `./db_migrate.py db upgrade` to upgrade your database.
86+
8187
## Good to go!
8288
- After that, enable the `USE_ELASTIC_SEARCH` flag and restart the webapp and you're good to go
8389

WSGI.py

100644100755
File mode changed.

db_create.py

100644100755
-6
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,3 @@
3333
db.session.add(main_cat)
3434

3535
db.session.commit()
36-
37-
# Create fulltext index
38-
39-
if app.config['USE_MYSQL']:
40-
db.engine.execute('ALTER TABLE ' + app.config['TABLE_PREFIX'] + 'torrents ADD FULLTEXT KEY (display_name)')
41-

db_migrate.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*-
3+
from nyaa import app, db
4+
from flask_script import Manager
5+
from flask_migrate import Migrate, MigrateCommand
6+
7+
migrate = Migrate(app, db)
8+
9+
manager = Manager(app)
10+
manager.add_command("db", MigrateCommand)
11+
12+
if __name__ == "__main__":
13+
manager.run()

import_to_es.py

100644100755
File mode changed.

migrations/README

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Generic single-database configuration.

migrations/alembic.ini

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# A generic, single database configuration.
2+
3+
[alembic]
4+
# template used to generate migration files
5+
# file_template = %%(rev)s_%%(slug)s
6+
7+
# set to 'true' to run the environment during
8+
# the 'revision' command, regardless of autogenerate
9+
# revision_environment = false
10+
11+
12+
# Logging configuration
13+
[loggers]
14+
keys = root,sqlalchemy,alembic
15+
16+
[handlers]
17+
keys = console
18+
19+
[formatters]
20+
keys = generic
21+
22+
[logger_root]
23+
level = WARN
24+
handlers = console
25+
qualname =
26+
27+
[logger_sqlalchemy]
28+
level = WARN
29+
handlers =
30+
qualname = sqlalchemy.engine
31+
32+
[logger_alembic]
33+
level = INFO
34+
handlers =
35+
qualname = alembic
36+
37+
[handler_console]
38+
class = StreamHandler
39+
args = (sys.stderr,)
40+
level = NOTSET
41+
formatter = generic
42+
43+
[formatter_generic]
44+
format = %(levelname)-5.5s [%(name)s] %(message)s
45+
datefmt = %H:%M:%S

migrations/env.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from __future__ import with_statement
2+
from alembic import context
3+
from sqlalchemy import engine_from_config, pool
4+
from logging.config import fileConfig
5+
import logging
6+
7+
# this is the Alembic Config object, which provides
8+
# access to the values within the .ini file in use.
9+
config = context.config
10+
11+
# Interpret the config file for Python logging.
12+
# This line sets up loggers basically.
13+
fileConfig(config.config_file_name)
14+
logger = logging.getLogger('alembic.env')
15+
16+
# add your model's MetaData object here
17+
# for 'autogenerate' support
18+
# from myapp import mymodel
19+
# target_metadata = mymodel.Base.metadata
20+
from flask import current_app
21+
config.set_main_option('sqlalchemy.url',
22+
current_app.config.get('SQLALCHEMY_DATABASE_URI'))
23+
target_metadata = current_app.extensions['migrate'].db.metadata
24+
25+
# other values from the config, defined by the needs of env.py,
26+
# can be acquired:
27+
# my_important_option = config.get_main_option("my_important_option")
28+
# ... etc.
29+
30+
31+
def run_migrations_offline():
32+
"""Run migrations in 'offline' mode.
33+
34+
This configures the context with just a URL
35+
and not an Engine, though an Engine is acceptable
36+
here as well. By skipping the Engine creation
37+
we don't even need a DBAPI to be available.
38+
39+
Calls to context.execute() here emit the given string to the
40+
script output.
41+
42+
"""
43+
url = config.get_main_option("sqlalchemy.url")
44+
context.configure(url=url)
45+
46+
with context.begin_transaction():
47+
context.run_migrations()
48+
49+
50+
def run_migrations_online():
51+
"""Run migrations in 'online' mode.
52+
53+
In this scenario we need to create an Engine
54+
and associate a connection with the context.
55+
56+
"""
57+
58+
# this callback is used to prevent an auto-migration from being generated
59+
# when there are no changes to the schema
60+
# reference: http://alembic.readthedocs.org/en/latest/cookbook.html
61+
def process_revision_directives(context, revision, directives):
62+
if getattr(config.cmd_opts, 'autogenerate', False):
63+
script = directives[0]
64+
if script.upgrade_ops.is_empty():
65+
directives[:] = []
66+
logger.info('No changes in schema detected.')
67+
68+
engine = engine_from_config(config.get_section(config.config_ini_section),
69+
prefix='sqlalchemy.',
70+
poolclass=pool.NullPool)
71+
72+
connection = engine.connect()
73+
context.configure(connection=connection,
74+
target_metadata=target_metadata,
75+
process_revision_directives=process_revision_directives,
76+
**current_app.extensions['migrate'].configure_args)
77+
78+
try:
79+
with context.begin_transaction():
80+
context.run_migrations()
81+
finally:
82+
connection.close()
83+
84+
if context.is_offline_mode():
85+
run_migrations_offline()
86+
else:
87+
run_migrations_online()

migrations/script.py.mako

+24
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"}

requirements.txt

+18-10
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
1+
alembic==0.9.2
12
appdirs==1.4.3
23
argon2-cffi==16.3.0
34
autopep8==1.3.1
45
blinker==1.4
56
cffi==1.10.0
67
click==6.7
78
dominate==2.3.1
8-
Flask==0.12.1
9+
elasticsearch==5.3.0
10+
elasticsearch-dsl==5.2.0
11+
Flask==0.12.2
912
Flask-Assets==0.12
1013
Flask-DebugToolbar==0.10.1
14+
Flask-Migrate==2.0.3
15+
flask-paginate==0.4.5
16+
Flask-Script==2.0.5
1117
Flask-SQLAlchemy==2.2
1218
Flask-WTF==0.14.2
1319
gevent==1.2.1
1420
greenlet==0.4.12
1521
itsdangerous==0.24
1622
Jinja2==2.9.6
1723
libsass==0.12.3
24+
Mako==1.0.6
1825
MarkupSafe==1.0
26+
mysql-replication==0.13
1927
mysqlclient==1.3.10
2028
orderedset==2.0
2129
packaging==16.8
2230
passlib==1.7.1
31+
progressbar2==3.20.0
2332
pycodestyle==2.3.1
2433
pycparser==2.17
34+
PyMySQL==0.7.11
2535
pyparsing==2.2.0
36+
python-dateutil==2.6.0
37+
python-editor==1.0.3
38+
python-utils==2.1.0
2639
six==1.10.0
27-
SQLAlchemy==1.1.9
40+
SQLAlchemy==1.1.10
2841
SQLAlchemy-FullText-Search==0.2.3
2942
SQLAlchemy-Utils==0.32.14
43+
statsd==3.2.1
44+
urllib3==1.21.1
3045
uWSGI==2.0.15
3146
visitor==0.1.3
3247
webassets==0.12.1
33-
Werkzeug==0.12.1
48+
Werkzeug==0.12.2
3449
WTForms==2.1
35-
## elasticsearch dependencies
36-
elasticsearch==5.3.0
37-
elasticsearch-dsl==5.2.0
38-
progressbar2==3.20.0
39-
mysql-replication==0.13
40-
flask-paginate==0.4.5
41-
statsd==3.2.1

run.py

100644100755
File mode changed.

sync_es.py

100644100755
File mode changed.

0 commit comments

Comments
 (0)