Flask-Migrate-1.2.0/0000775000175000017500000000000012267017646014743 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/flask_migrate/0000775000175000017500000000000012267017646017553 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/flask_migrate/__init__.py0000664000175000017500000001477112267017221021663 0ustar miguelmiguel00000000000000import os from flask import current_app from flask.ext.script import Manager from alembic.config import Config as AlembicConfig from alembic import command class _MigrateConfig(object): def __init__(self, db, directory): self.db = db self.directory = directory @property def metadata(self): """Backwards compatibility, in old releases app.extensions['migrate'] was set to db, and env.py accessed app.extensions['migrate'].metadata""" return self.db.metadata class Migrate(object): def __init__(self, app = None, db = None, directory = 'migrations'): if app is not None and db is not None: self.init_app(app, db, directory) def init_app(self, app, db, directory = 'migrations'): if not hasattr(app, 'extensions'): app.extensions = {} app.extensions['migrate'] = _MigrateConfig(db, directory) class Config(AlembicConfig): def get_template_directory(self): package_dir = os.path.abspath(os.path.dirname(__file__)) return os.path.join(package_dir, 'templates') def _get_config(directory): if directory is None: directory = current_app.extensions['migrate'].directory config = Config(os.path.join(directory, 'alembic.ini')) config.set_main_option('script_location', directory) return config MigrateCommand = Manager(usage = 'Perform database migrations') @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "migration script directory (default is 'migrations')") def init(directory = None): "Generates a new migration" if directory is None: directory = current_app.extensions['migrate'].directory config = Config() config.set_main_option('script_location', directory) config.config_file_name = os.path.join(directory, 'alembic.ini') command.init(config, directory, 'flask') @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def current(directory = None): "Display the current revision for each database." config = _get_config(directory) command.current(config) @MigrateCommand.option('-r', '--rev-range', dest = 'rev_range', default = None, help = "Specify a revision range; format is [start]:[end]") @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def history(directory = None, rev_range = None): "List changeset scripts in chronological order." config = _get_config(directory) command.history(config, rev_range) @MigrateCommand.option('--sql', dest = 'sql', action = 'store_true', default = False, help = "Don't emit SQL to database - dump to standard output instead") @MigrateCommand.option('--autogenerate', dest = 'autogenerate', action = 'store_true', default = False, help = "Populate revision script with andidate migration operatons, based on comparison of database to model") @MigrateCommand.option('-m', '--message', dest = 'message', default = None) @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def revision(directory = None, message = None, autogenerate = False, sql = False): "Create a new revision file." config = _get_config(directory) command.revision(config, message, autogenerate = autogenerate, sql = sql) @MigrateCommand.option('--sql', dest = 'sql', action = 'store_true', default = False, help = "Don't emit SQL to database - dump to standard output instead") @MigrateCommand.option('-m', '--message', dest = 'message', default = None) @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def migrate(directory = None, message = None, sql = False): "Alias for 'revision --autogenerate'" config = _get_config(directory) command.revision(config, message, autogenerate = True, sql = sql) @MigrateCommand.option('--tag', dest = 'tag', default = None, help = "Arbitrary 'tag' name - can be used by custom env.py scripts") @MigrateCommand.option('--sql', dest = 'sql', action = 'store_true', default = False, help = "Don't emit SQL to database - dump to standard output instead") @MigrateCommand.option('revision', default = None, help = "revision identifier") @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def stamp(directory = None, revision = 'head', sql = False, tag = None): "'stamp' the revision table with the given revision; don't run any migrations" config = _get_config(directory) command.stamp(config, revision, sql = sql, tag = tag) @MigrateCommand.option('--tag', dest = 'tag', default = None, help = "Arbitrary 'tag' name - can be used by custom env.py scripts") @MigrateCommand.option('--sql', dest = 'sql', action = 'store_true', default = False, help = "Don't emit SQL to database - dump to standard output instead") @MigrateCommand.option('revision', nargs = '?', default = 'head', help = "revision identifier") @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def upgrade(directory = None, revision = 'head', sql = False, tag = None): "Upgrade to a later version" config = _get_config(directory) command.upgrade(config, revision, sql = sql, tag = tag) @MigrateCommand.option('--tag', dest = 'tag', default = None, help = "Arbitrary 'tag' name - can be used by custom env.py scripts") @MigrateCommand.option('--sql', dest = 'sql', action = 'store_true', default = False, help = "Don't emit SQL to database - dump to standard output instead") @MigrateCommand.option('revision', nargs = '?', default = "-1", help = "revision identifier") @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def downgrade(directory = None, revision = '-1', sql = False, tag = None): "Revert to a previous version" config = _get_config(directory) command.downgrade(config, revision, sql = sql, tag = tag) @MigrateCommand.option('-d', '--directory', dest = 'directory', default = None, help = "Migration script directory (default is 'migrations')") def branches(directory = None): "Lists revisions that have broken the source tree into two versions representing two independent sets of changes" config = _get_config(directory) command.branches(config) Flask-Migrate-1.2.0/flask_migrate/templates/0000775000175000017500000000000012267017646021551 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/flask_migrate/templates/flask/0000775000175000017500000000000012267017646022651 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/flask_migrate/templates/flask/README0000775000175000017500000000004612247271311023521 0ustar miguelmiguel00000000000000Generic single-database configuration.Flask-Migrate-1.2.0/flask_migrate/templates/flask/env.py0000664000175000017500000000415612267017221024006 0ustar miguelmiguel00000000000000from __future__ import with_statement from alembic import context from sqlalchemy import engine_from_config, pool from logging.config import fileConfig # 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) # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata from flask import current_app config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI')) target_metadata = current_app.extensions['migrate'].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: # my_important_option = config.get_main_option("my_important_option") # ... etc. 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) 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. """ engine = engine_from_config( config.get_section(config.config_ini_section), prefix='sqlalchemy.', poolclass=pool.NullPool) connection = engine.connect() context.configure( connection=connection, target_metadata=target_metadata ) try: with context.begin_transaction(): context.run_migrations() finally: connection.close() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() Flask-Migrate-1.2.0/flask_migrate/templates/flask/alembic.ini.mako0000664000175000017500000000140212247271311025656 0ustar miguelmiguel00000000000000# A generic, single database configuration. [alembic] # template used to generate migration files # file_template = %%(rev)s_%%(slug)s # set to 'true' to run the environment during # the 'revision' command, regardless of autogenerate # revision_environment = false # 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 Flask-Migrate-1.2.0/flask_migrate/templates/flask/script.py.mako0000775000175000017500000000063412247271311025450 0ustar miguelmiguel00000000000000"""${message} Revision ID: ${up_revision} Revises: ${down_revision} Create Date: ${create_date} """ # revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} from alembic import op import sqlalchemy as sa ${imports if imports else ""} def upgrade(): ${upgrades if upgrades else "pass"} def downgrade(): ${downgrades if downgrades else "pass"} Flask-Migrate-1.2.0/tests/0000775000175000017500000000000012267017646016105 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/tests/test_migrate.py0000664000175000017500000000161112247273523021141 0ustar miguelmiguel00000000000000import os import shutil from exceptions import OSError import unittest class TestMigrate(unittest.TestCase): def setUp(self): os.chdir(os.path.split(os.path.abspath(__file__))[0]) try: os.remove('app.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass os.system('python app.py db init') os.system('python app.py db migrate') os.system('python app.py db upgrade') def tearDown(self): try: os.remove('app.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass def test_migrate_upgrade(self): from app import db, User db.session.add(User(name = 'test')) db.session.commit() if __name__ == '__main__': unittest.main() Flask-Migrate-1.2.0/tests/app.pyc0000664000175000017500000000201212247273150017365 0ustar miguelmiguel00000000000000ó ÉrRc@sĚddlmZddlmZddlmZddlmZmZee ƒZ de j ds     Flask-Migrate-1.2.0/tests/__init__.py0000664000175000017500000000000112247271311020172 0ustar miguelmiguel00000000000000 Flask-Migrate-1.2.0/tests/test_migrate_custom_directory.py0000664000175000017500000000162012267017221024610 0ustar miguelmiguel00000000000000import os import shutil from exceptions import OSError import unittest class TestMigrate(unittest.TestCase): def setUp(self): os.chdir(os.path.split(os.path.abspath(__file__))[0]) try: os.remove('app2.db') except OSError: pass try: shutil.rmtree('temp_folder') except OSError: pass os.system('python app2.py db init') os.system('python app2.py db migrate') os.system('python app2.py db upgrade') def tearDown(self): try: os.remove('app2.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass def test_migrate_upgrade(self): from app2 import db, User db.session.add(User(name = 'test')) db.session.commit() if __name__ == '__main__': unittest.main() Flask-Migrate-1.2.0/tests/app2.py0000664000175000017500000000105612267017221017310 0ustar miguelmiguel00000000000000from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app2.db' db = SQLAlchemy(app) migrate = Migrate(app, db, directory = 'temp_folder/temp_migrations') manager = Manager(app) manager.add_command('db', MigrateCommand) class User(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String(128)) if __name__ == '__main__': manager.run() Flask-Migrate-1.2.0/tests/app.py0000664000175000017500000000100212247271311017215 0ustar miguelmiguel00000000000000from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' db = SQLAlchemy(app) migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) class User(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String(128)) if __name__ == '__main__': manager.run() Flask-Migrate-1.2.0/tests/__init__.pyc0000664000175000017500000000022712247273150020352 0ustar miguelmiguel00000000000000ó ÉrRc@sdS(N((((s@/home/miguel/Documents/dev/flask/Flask-Migrate/tests/__init__.pytsFlask-Migrate-1.2.0/tests/test_migrate.pyc0000664000175000017500000000337112247273150021305 0ustar miguelmiguel00000000000000ó ÉrRc@sjddlZddlZddlmZddlZdejfd„ƒYZedkrfejƒndS(i˙˙˙˙N(tOSErrort TestMigratecBs#eZd„Zd„Zd„ZRS(cCsžtjtjjtjjtƒƒdƒytjdƒWntk rMnXytj dƒWntk rrnXtj dƒtj dƒtj dƒdS(Nisapp.dbt migrationsspython app.py db initspython app.py db migratespython app.py db upgrade( tostchdirtpathtsplittabspatht__file__tremoveRtshutiltrmtreetsystem(tself((sD/home/miguel/Documents/dev/flask/Flask-Migrate/tests/test_migrate.pytsetUps)    cCsNytjdƒWntk r$nXytjdƒWntk rInXdS(Nsapp.dbR(RR RR R (R ((sD/home/miguel/Documents/dev/flask/Flask-Migrate/tests/test_migrate.pyttearDowns  cCs@ddlm}m}|jj|ddƒƒ|jjƒdS(Ni˙˙˙˙(tdbtUsertnamettest(tappRRtsessiontaddtcommit(R RR((sD/home/miguel/Documents/dev/flask/Flask-Migrate/tests/test_migrate.pyttest_migrate_upgrade s(t__name__t __module__RRR(((sD/home/miguel/Documents/dev/flask/Flask-Migrate/tests/test_migrate.pyRs  t__main__( RR t exceptionsRtunittesttTestCaseRRtmain(((sD/home/miguel/Documents/dev/flask/Flask-Migrate/tests/test_migrate.pyts    Flask-Migrate-1.2.0/MANIFEST.in0000664000175000017500000000010312267017221016460 0ustar miguelmiguel00000000000000include README.md LICENSE flask_migrate/templates/flask/* tests/* Flask-Migrate-1.2.0/setup.cfg0000664000175000017500000000007312267017646016564 0ustar miguelmiguel00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 Flask-Migrate-1.2.0/Flask_Migrate.egg-info/0000775000175000017500000000000012267017646021145 5ustar miguelmiguel00000000000000Flask-Migrate-1.2.0/Flask_Migrate.egg-info/requires.txt0000664000175000017500000000007712267017646023551 0ustar miguelmiguel00000000000000Flask>=0.9 Flask-SQLAlchemy>=1.0 alembic>=0.6 Flask-Script>=0.6Flask-Migrate-1.2.0/Flask_Migrate.egg-info/SOURCES.txt0000664000175000017500000000114412267017646023031 0ustar miguelmiguel00000000000000LICENSE MANIFEST.in README.md setup.py Flask_Migrate.egg-info/PKG-INFO Flask_Migrate.egg-info/SOURCES.txt Flask_Migrate.egg-info/dependency_links.txt Flask_Migrate.egg-info/not-zip-safe Flask_Migrate.egg-info/requires.txt Flask_Migrate.egg-info/top_level.txt flask_migrate/__init__.py flask_migrate/templates/flask/README flask_migrate/templates/flask/alembic.ini.mako flask_migrate/templates/flask/env.py flask_migrate/templates/flask/script.py.mako tests/__init__.py tests/__init__.pyc tests/app.py tests/app.pyc tests/app2.py tests/test_migrate.py tests/test_migrate.pyc tests/test_migrate_custom_directory.pyFlask-Migrate-1.2.0/Flask_Migrate.egg-info/not-zip-safe0000664000175000017500000000000112247273304023364 0ustar miguelmiguel00000000000000 Flask-Migrate-1.2.0/Flask_Migrate.egg-info/top_level.txt0000664000175000017500000000001612267017646023674 0ustar miguelmiguel00000000000000flask_migrate Flask-Migrate-1.2.0/Flask_Migrate.egg-info/dependency_links.txt0000664000175000017500000000000112267017646025213 0ustar miguelmiguel00000000000000 Flask-Migrate-1.2.0/Flask_Migrate.egg-info/PKG-INFO0000664000175000017500000000144112267017646022242 0ustar miguelmiguel00000000000000Metadata-Version: 1.1 Name: Flask-Migrate Version: 1.2.0 Summary: SQLAlchemy database migrations for Flask applications using Alembic Home-page: http://github.com/miguelgrinberg/flask-migrate/ Author: Miguel Grinberg Author-email: miguelgrinberg50@gmail.com License: MIT Description: Flask-Migrate -------------- SQLAlchemy database migrations for Flask applications using Alembic. Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Migrate-1.2.0/LICENSE0000664000175000017500000000207212247271311015736 0ustar miguelmiguel00000000000000The MIT License (MIT) Copyright (c) 2013 Miguel Grinberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Flask-Migrate-1.2.0/setup.py0000664000175000017500000000212712267017240016445 0ustar miguelmiguel00000000000000""" Flask-Migrate -------------- SQLAlchemy database migrations for Flask applications using Alembic. """ from setuptools import setup setup( name='Flask-Migrate', version='1.2.0', url='http://github.com/miguelgrinberg/flask-migrate/', license='MIT', author='Miguel Grinberg', author_email='miguelgrinberg50@gmail.com', description='SQLAlchemy database migrations for Flask applications using Alembic', long_description=__doc__, packages=['flask_migrate'], zip_safe=False, include_package_data=True, platforms='any', install_requires=[ 'Flask>=0.9', 'Flask-SQLAlchemy>=1.0', 'alembic>=0.6', 'Flask-Script>=0.6' ], test_suite = "tests", classifiers=[ 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ] ) Flask-Migrate-1.2.0/README.md0000664000175000017500000000407712247271311016217 0ustar miguelmiguel00000000000000Flask-Migrate ============= Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are provided as command line arguments for Flask-Script. Example ------- This is an example application that handles database migrations through Flask-Migrate: from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' db = SQLAlchemy(app) migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) class User(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String(128)) if __name__ == '__main__': manager.run() With the above application you can create the database or enable migrations if the database already exists with the following command: $ python app.py db init This will add a `migrations` folder to your application. The contents of this folder need to be added to version control along with your other source files. You can then generate an initial migration: $ python app.py db migrate The migration script needs to be reviewed and edited, as Alembic currently does not detect every change you make to your models. In particular, Alembic is currently unable to detect indexes. Once finalized, the migration script also needs to be added to version control. Then you can apply the migration to the database: $ python app.py db upgrade Then each time the database models change repeat the `migrate` and `upgrade` commands. To sync the database in another system just refresh the `migrations` folder from source control and run the `upgrade` command. To see all the commands that are available run this command: $ python app.py db --help Resources --------- - [Documentation](http://pythonhosted.org/Flask-Migrate) - [pypi](https://pypi.python.org/pypi/Flask-Migrate) Flask-Migrate-1.2.0/PKG-INFO0000664000175000017500000000144112267017646016040 0ustar miguelmiguel00000000000000Metadata-Version: 1.1 Name: Flask-Migrate Version: 1.2.0 Summary: SQLAlchemy database migrations for Flask applications using Alembic Home-page: http://github.com/miguelgrinberg/flask-migrate/ Author: Miguel Grinberg Author-email: miguelgrinberg50@gmail.com License: MIT Description: Flask-Migrate -------------- SQLAlchemy database migrations for Flask applications using Alembic. Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules