pax_global_header00006660000000000000000000000064145736502570014530gustar00rootroot0000000000000052 comment=faf06d1460bc76fe6951e9497352fcd3d3dfce98 flask-migrate-4.0.7/000077500000000000000000000000001457365025700142665ustar00rootroot00000000000000flask-migrate-4.0.7/.github/000077500000000000000000000000001457365025700156265ustar00rootroot00000000000000flask-migrate-4.0.7/.github/FUNDING.yml000066400000000000000000000001301457365025700174350ustar00rootroot00000000000000github: miguelgrinberg patreon: miguelgrinberg custom: https://paypal.me/miguelgrinberg flask-migrate-4.0.7/.github/ISSUE_TEMPLATE/000077500000000000000000000000001457365025700200115ustar00rootroot00000000000000flask-migrate-4.0.7/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000016561457365025700225130ustar00rootroot00000000000000--- name: Bug report about: File a bug report title: '' labels: '' assignees: '' --- **IMPORTANT**: If you have a question, or if you are not sure if you have found a bug in this package or in your own code, then you are in the wrong place. Hit back in your web browser, and then open a GitHub Discussion instead. Likewise, if you are unable to provide the information requested below, open a Discussion to troubleshoot your issue. **Describe the bug** A clear and concise description of what the bug is. If you are getting errors, please include the complete error message, including the stack trace. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Logs** Please provide relevant logs or script output. **Additional context** Add any other context about the problem here. flask-migrate-4.0.7/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002541457365025700220020ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: GitHub Discussions url: https://github.com/miguelgrinberg/Flask-Migrate/discussions about: Ask questions here. flask-migrate-4.0.7/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000012141457365025700235340ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Logs** Please provide relevant logs or script output. **Additional context** Add any other context or screenshots about the feature request here. flask-migrate-4.0.7/.github/workflows/000077500000000000000000000000001457365025700176635ustar00rootroot00000000000000flask-migrate-4.0.7/.github/workflows/tests.yml000066400000000000000000000017671457365025700215630ustar00rootroot00000000000000name: build on: push: branches: - main pull_request: branches: - main jobs: lint: name: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 - run: python -m pip install --upgrade pip wheel - run: pip install tox tox-gh-actions - run: tox -eflake8 - run: tox -edocs tests: name: tests strategy: matrix: # TODO: add windows-latest os: [ubuntu-latest, macos-latest] python: ['3.8', '3.9', '3.10', '3.11', 'pypy-3.9'] sqla: ['sqlalchemy<2 flask-sqlalchemy<3.1', 'sqlalchemy>=2 flask-sqlalchemy>=3.1'] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} - run: python -m pip install --upgrade pip wheel - run: pip install tox tox-gh-actions - run: SQLALCHEMY_VERSION="${{ matrix.sqla }}" tox flask-migrate-4.0.7/.gitignore000066400000000000000000000005741457365025700162640ustar00rootroot00000000000000*.py[cod] # C extensions *.so # Packages *.egg *.egg-info dist build eggs parts var sdist develop-eggs .installed.cfg lib lib64 # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox nosetests.xml # Unit test temporary files tests/temp_folder # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Sphinx build files docs/_build/flask-migrate-4.0.7/CHANGES.md000066400000000000000000000635241457365025700156720ustar00rootroot00000000000000# Flask-Migrate Change Log **Release 4.0.7** - 2024-03-11 - Regression from #438: check `g.x_arg` exists before accessing it [#541](https://github.com/miguelgrinberg/flask-migrate/issues/541) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7e8032c61e5c47f4e50b03dcf98c3b20dd5a8e55)) (thanks **Skye Im**!) **Release 4.0.6** - 2024-03-09 - Accept `-x` options for all db commands [#438](https://github.com/miguelgrinberg/flask-migrate/issues/438) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/6f3f889c36030134f87dc1db327c2385d873a4d6)) - Add `--purge` flag to the `stamp` command [#540](https://github.com/miguelgrinberg/flask-migrate/issues/540) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/af67bb093df5652c867b88880c5934bfc68313cc)) (thanks **Jono N**!) **Release 4.0.5** - 2023-09-12 - Compatiblity fixes for Flask-SQLAlchemy >= 3.1 [#526](https://github.com/miguelgrinberg/flask-migrate/issues/526) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/f562178bbe1912912f3cb6877cbae8b0899c74da)) (thanks **David Lord**!) - Allow `process_revision_directives` option to be configurable [#523](https://github.com/miguelgrinberg/flask-migrate/issues/523) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/821e37fcc4a5e339f197153cdbb4dd2316cbd44b)) (thanks **llc**!) - Stop testing Python 3.7, as Flask-SQLAlchemy 3.1 stopped supporting it ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8d175193f00bf4e5578f0142d011093d8cd53d57)) **Release 4.0.4** - 2023-02-02 - Correctly obtain database URL with SQLAlchemy 2.0 [#505](https://github.com/miguelgrinberg/flask-migrate/issues/505) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c8cd02c5d3d43bbab462b863db5417b5d69228bb)) **Release 4.0.3** - 2023-01-29 - Remove legacy __future__ import in Alembic templates [#504](https://github.com/miguelgrinberg/flask-migrate/issues/504) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7a388cfe320254735f4ed65ac655caaf0cae8b28)) (thanks **Pamela Fox**!) - Add SQLAlchemy 1.4 and 2.0 to the test matrix ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7a725f2e3267f1c3bb4920cd3bff3a9ff1d7eb6e)) - Switch to pytest as test runner ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5acd794048d050f85b5dea93052f96abd8a583f2)) **Release 4.0.2** - 2023-01-18 - Support "check" command [#502](https://github.com/miguelgrinberg/flask-migrate/issues/502) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/1a893b4fca280f82b1aada6458b7c866c6d3c953)) (thanks **Masamitsu MURASE**!) **Release 4.0.1** - 2023-01-05 - Do not use deprecated functions in Flask-SQLAlchemy 3.0 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7cb4236327ea04fc6be8a17bbfadae6de7bfbc8b)) - Stop building Python 3.6 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c9534b39df49884e1b62592c486ed0d5565b3321)) - Remove tests from pypi package ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/2dd0c25caa5c43b452109f64c8e33ccc048ca210)) **Release 4.0.0** - 2022-11-13 - Updates for Flask-SQLAlchemy 3.x compatiblity ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/51752948aabdb68f7c032e1c1fc8317f895e10a6)) - Enable type comparison and batch mode by default ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/a3085b34e5b1865d2b773248b37468764df7c312)) - Option to rename "db" command group to a custom name ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/b9c9d35744a08f4f62084ce6e3ddf30d21431dc7)) - Better handling of MetaData instances in templates ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c051a000c1518a71e0a5d045c1f8065b9add5122)) - Set options correctly when `revision --autogenerate` is used [#463](https://github.com/miguelgrinberg/flask-migrate/issues/463) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/f7f15e2623866110974fddcdbea87ccbf1d74a40)) (thanks **Frazer McLean**!) - Documentation section on configuring Alembic ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/28522143f4e1371f08fa8bac8d3ba1f6b04e0f72)) - Upgrade build to pypy-3.9 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/dfaeeff71739f75655f9d1e7f88bc70cb87a1f2b)) - Add Python 3.10 to build ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/a41df8748e8d3b1a6d0909d5d7fe46a55c7f1c9b)) - Add Python 3.11 to build ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/370b9151b6ae3e23675c1a7566d8f09402beb3d6)) - Specify license in project metadata [#489](https://github.com/miguelgrinberg/flask-migrate/issues/489) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/095b0ecbdfd496326978708ad2e7fc0025832964)) (thanks **Frazer McLean**!) - Remove tests from pypi package ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/2dd0c25caa5c43b452109f64c8e33ccc048ca210)) **Release 3.1.0** - 2021-08-01 - Added `list-templates` command and support for custom templates ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/0f9094a750205c1db1fe178d0d037e529de403ae)) - Alembic templates for [aioflask](https://github.com/miguelgrinberg/aioflask) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/fbaaa3787d0e03f5aafaea6fd7c2956362a57c52)) - Improved project structure ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/074cbc9cae4b6ebb7d013adcec42e070be1ae6b3)) **Release 3.0.1** - 2021-05-31 - Add support for Alchemical in addition to Flask-SQLAlchemy ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/113115d7f37a713d1f32be53a1e43564b9bb3dea)) - Remove Flask-Script references from the documentation ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/699e136e1ff8e2e75e6fcd957c4ebf332a4969a9)) **Release 3.0.0** - 2021-05-15 - Remove support for Flask-Script [#403](https://github.com/miguelgrinberg/flask-migrate/issues/403) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/a1787cf18fb4d5ec7369280afe1a59349f7544b8)) - Use unittest testrunner [#397](https://github.com/miguelgrinberg/flask-migrate/issues/397) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5e75b1b574dd7ee991ca2fae0b2ccd63a0f98d81)) (thanks **Jürgen Gmach**!) - Remove dependency on six package [#395](https://github.com/miguelgrinberg/flask-migrate/issues/395) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/4ad897f1c3522ecf529cb83f70ef72bc3c32ba6f)) (thanks **Jürgen Gmach**!) - Added sphinx build files to .gitignore file [#394](https://github.com/miguelgrinberg/flask-migrate/issues/394) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/6566e3dc5d5aa6dc7ca7a6228655f0a9d78d42e6)) (thanks **Jürgen Gmach**!) - Fix Sphinx warning [#393](https://github.com/miguelgrinberg/flask-migrate/issues/393) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/a2d31b723517a9f72a9735ff70d858f7158dd4b3)) (thanks **Jürgen Gmach**!) **Release 2.7.0** - 2021-02-21 - Reuse engine from Flask-SQLAlchemy [#343](https://github.com/miguelgrinberg/flask-migrate/issues/343) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8f8ded8799c65e2b3490a82b5e3a3953c33c58dd)) - Update logging configuration to include Flask-Migrate's logger ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/3a11cd8392733bd8315458c47d769d952494bdd7)) **Release 2.6.0** - 2021-01-19 - Removed deprecated --head-only option [#380](https://github.com/miguelgrinberg/flask-migrate/issues/380) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ae0a5a922106d67605adcebe9e3f13b1ed5f84e8)) - Initialize logger with a name [#374](https://github.com/miguelgrinberg/flask-migrate/issues/374) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/4887bd53bc08f10087fe27a4a7d9fe853031cdcf)) (thanks **maquino1985**!) - Move import to the top in env.py file to avoid linter warnings [#349](https://github.com/miguelgrinberg/flask-migrate/issues/349) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/b34d9e3ff79ffb2f6c0204289f697a08852d0859)) (thanks **James Addison**!) - Add a note to the documentation regarding logging [#330](https://github.com/miguelgrinberg/flask-migrate/issues/330) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/f969b5ea087f2d9bf646492e1a5ca23535dfac5f)) (thanks **Oliver Evans**!) - Move builds to GitHub actions ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c4a515105e84ae201208cd02159116653dc5e821)) **Release 2.5.3** - 2020-03-14 - Allow `Path` objects to be used as `directory` parameter [#319](https://github.com/miguelgrinberg/flask-migrate/issues/319) Closes [#318](https://github.com/miguelgrinberg/flask-migrate/issues/318). ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/399cb28cc128539111234f7ecea0b3187325af82)) (thanks **Nicolas Schneider**!) - Use same database URLs as Flask-SQLAlchemy [#276](https://github.com/miguelgrinberg/flask-migrate/issues/276) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/4a180b711bf87572617a0b7caad0a7151f53fde7)) - Document how to set up with init_app method [#302](https://github.com/miguelgrinberg/flask-migrate/issues/302) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/6a76c245740d9af3ad5eef56ee9ff15f8205a0ca)) (thanks **Kyle Lawlor**!) - Document how to include a message in initial migrate. [#313](https://github.com/miguelgrinberg/flask-migrate/issues/313) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/aa05b836a2fe89363bc2d61a699acd54aca52bd5)) (thanks **Bernardo Gomes**!) - Remove checks for alembic 0.7.0 [#278](https://github.com/miguelgrinberg/flask-migrate/issues/278) Flask-Migrate requires alembic >= 0.7 in its setup.py file, which makes all the checks for this version obsolete. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/97b8d334324ecb043fb0ddaef1660f36832af02c)) (thanks **Tadej Borovšak**!) - Use sys.executable in tests [#290](https://github.com/miguelgrinberg/flask-migrate/issues/290) Also re-order imports. Closes https://github.com/miguelgrinberg/Flask-Migrate/issues/289 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/e5135e5a6a31675d5fb10febe815b257d82632a2)) (thanks **John Vandenberg**!) - Cosmetic improvements to help messages [#284](https://github.com/miguelgrinberg/flask-migrate/issues/284) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d501d8b2923187df00d6bb1ec1f04694ab3f9667)) (thanks **Marat Sharafutdinov**!) **Release 2.5.2** - 2019-05-25 - add python 3.7 builds, remove 3.4 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)) - auto-generate change log during release ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/250a3110ad84ba331ffc7cb871e5a12fddc55f2d)) - Nicer change log ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/829edefe09dff82b6c91203dd0f5b5795bf9c8d1)) **Release 2.5.1** - 2019-05-20 - Fix `__version__` file not found in sdist [#267](https://github.com/miguelgrinberg/flask-migrate/issues/267) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8ba8d7dca6cb233280d4644fc8d81cbba123a5ad)) (thanks **Christoph Gohlke**!) **Release 2.5.0** - 2019-05-19 - helper release script ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/fb041b9b9221e7125e5ee27dd9eb7514cf143181)) - support % character in database URLs [#59](https://github.com/miguelgrinberg/flask-migrate/issues/59) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/4663819b416dfb5a450fe948e84111af3712078d)) - log command output in unit tests ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/506f3541c04dd0b2c020dbafc60a93fb541ca324)) - add a section on why use this extension to the docs [#101](https://github.com/miguelgrinberg/flask-migrate/issues/101) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5467b295f7912d195333482325052eae81d30f7a)) **Release 2.4.0** - 2019-02-16 - updates to env.py ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/2a1ae1b9aa62c246fca2b2f1566284de8d4b940b)) - Link to binds is unreachable [#244](https://github.com/miguelgrinberg/flask-migrate/issues/244) The original link redirects to flask-sqlalchemy.pocoo.org Addressing it directly works and redirects to the latest version of flask-sqlalchemy ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/eb2ab8f797a179d807b6560947f4498bb543def0)) (thanks **FaBrand**!) **Release 2.3.1** - 2018-11-28 - Don't swallow transaction errors [#236](https://github.com/miguelgrinberg/flask-migrate/issues/236) A change proposed by @kjohnsen from [#216](https://github.com/miguelgrinberg/flask-migrate/issues/216). You can read more starting with [this comment](https://github.com/miguelgrinberg/Flask-Migrate/issues/216#issuecomment-408159125). ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/87b40ec9b2113ab87f1dc41c4eb517e8ff0f5dd8)) (thanks **Nikolay Shebanov**!) **Release 2.3.0** - 2018-10-05 - use the root logger for alembic error messages ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/fa3b45ea6ecd16f436bbdee210745335128bf514)) - Add indicate-current option into history command [#192](https://github.com/miguelgrinberg/flask-migrate/issues/192) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/1fa1936375bf609e9dab401e26f46f715f5b272b)) (thanks **misebox**!) **Release 2.2.1** - 2018-06-18 - dependency updates ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5d61c191d7d8853f81e4fe71609b5ae315604c52)) - add pypy3 to test matrix ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/1cc819e9f2a17435429c16531043d0a874f76288)) **Release 2.2.0** - 2018-06-13 - suppress stack traces on command errors [#204](https://github.com/miguelgrinberg/flask-migrate/issues/204) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/2dd45d0037cb62bc7a8a981f0de70071b891a2ff)) - Fix typo in docs [#207](https://github.com/miguelgrinberg/flask-migrate/issues/207) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/817893fe16eb5361469af671c52d8276b69efeab)) (thanks **Grey Li**!) - Update documentation link [#206](https://github.com/miguelgrinberg/flask-migrate/issues/206) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/98374a6ac1006fe37ef6f09674ebaa094214ff3e)) (thanks **Grey Li**!) - [#182](https://github.com/miguelgrinberg/flask-migrate/issues/182): clear executable permission [#183](https://github.com/miguelgrinberg/flask-migrate/issues/183) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ee0b47ede1e88340c390fca9d0c27a9c8a7e3a9c)) (thanks **Christopher Yeleighton**!) **Release 2.1.1** - 2017-08-28 - Make directory as optional parameter ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7e6f511b050a023c9388868b97d7905b7571c16f)) (thanks **Diego Oliveira**!) - Update CHANGELOG.md ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/dcffe1e91f9f5cfc29c5cf5f285ef9a4169113bb)) - updated README.md to use flask cli in examples ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/349826ef53f607fd5e866919f40b16315a2127cc)) **Release 2.1.0** - 2017-07-28 - Remove the Flask-Script dependency in setup.py ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/7bd5ef80016257ea56a1d10f917a361a13b6aad9)) **Release 2.0.4** - 2017-05-31 - Change an Alembic doc link to http from https The SSL certificate is not valid for the alembic subdomain. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/00e8192f56f778939fd819a799a9b26010b46e2e)) (thanks **bovarysme**!) - Update links pointing to the old Alembic doc [#152](https://github.com/miguelgrinberg/flask-migrate/issues/152) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/81367408c46ecd96b2352f6e309dcb02dfc359e9)) (thanks **bovarysme**!) - allow -x argument for migrate command [#148](https://github.com/miguelgrinberg/flask-migrate/issues/148) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/3293d835811924822cf0e8d321760ddc482ea5f2)) (thanks **Tim Mundt**!) - stop building python 2.6 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5f34c5cd9610f2e3194672a350f57c55cb7edd25)) **Release 2.0.3** - 2017-01-30 - remove py33 builds, add py36 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c25ef622efc4dc28452124f56fc9bfa550ce858e)) - Support multiple -x arguments in Flask-Script interface [#103](https://github.com/miguelgrinberg/flask-migrate/issues/103) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d2947338d673041b6198b909a9f9381b73f6bf99)) - Fix autogenerate typos. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/19af3191d8245c110860f01bb48b02b0e2d9351a)) (thanks **Sorin Muntean**!) **Release 2.0.2** - 2016-12-09 - Merge branch 'briancappello-application_factory_kwargs' ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/4ab45f60bea8227f94adbf5de1e8509ef79afa66)) - support passing alembic context kwargs from constructor into init_app ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/57c82f35366ea9122908e3b0cbdcf536d430c2de)) (thanks **Brian Cappello**!) - fix link for alembics command reference page ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/bfbfcb24abf3ede22104211157f05d3f370ed467)) (thanks **Brian Cappello**!) - update autogenerate capabilities ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/118b84d384106ebfde767931119204b80fcbbac5)) (thanks **Brian Cappello**!) **Release 2.0.1** - 2016-11-13 - Imports at top of file as specified by Flake8 and added branch label. Moving the imports to the top of the file will prevent an error: 'E402 module level import not at top of file'. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c95c20134655cbe8f771a7e47f6d3fd4ed3e8cb6)) (thanks **Maico Timmerman**!) - Fix typo [#126](https://github.com/miguelgrinberg/flask-migrate/issues/126) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/109f42fc1752422c0e3899942abe10020641edf6)) (thanks **Wells Lucas Santo**!) - Fix typo [#123](https://github.com/miguelgrinberg/flask-migrate/issues/123) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/f37bdb70529e5f984b9008eace59244a293ea3db)) (thanks **Jeff Widman**!) - flask cli documentation updates ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/254b88bc4bdafd8fb9210b37f772a72035a12cff)) **Release 2.0.0** - 2016-07-31 - add travis builds for python 3.5 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/080b7100e2f8077d95deb7c5dcdd5adb792f528c)) - Support the new flask cli based on click [#114](https://github.com/miguelgrinberg/flask-migrate/issues/114) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8c208b54837ccbf65eee8d95fc623057e2753b4e)) **Release 1.8.1** - 2016-07-10 - Allow to init_app correctly without specifying db. [#118](https://github.com/miguelgrinberg/flask-migrate/issues/118) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/e339f27b8ee3e932d74fff91344b615fe6170333)) (thanks **Victor Akimov**!) **Release 1.8.0** - 2016-02-24 - Allow db to be provided separately from the app ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d612c10c05ceab7e1131839ab8a7eadcc4a71beb)) - Added missing Python 2 version classifier to package ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/6f321543fec6c04b445c34c312092c45deaf2d29)) - Fix the link for flask-sqlalchemy binds [#99](https://github.com/miguelgrinberg/flask-migrate/issues/99) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/6bf0452b084f14d06e56784465240e0258b710cb)) (thanks **lord63**!) - Update the way to import the flask extension [#98](https://github.com/miguelgrinberg/flask-migrate/issues/98) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/c27cfea43d923b991b5f609a94a58efcdca4fe3b)) (thanks **lord63**!) **Release 1.7.0** - 2015-12-28 - configuration callbacks ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/835d3e4b33bfbd7dae2166b88c49aee8f5fbeac0)) - Update __init__.py Update description of edit command. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/3a657dcb683ff3b91cb9e2393fbdaaa11ea33b8a)) (thanks **Kostyantyn Leschenko**!) - fixed link in documentation ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/738d33cd76185455063d9499f7752b846193889a)) **Release 1.6.0** - 2015-09-17 - Add edit command [#76](https://github.com/miguelgrinberg/flask-migrate/issues/76) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/e9c855ca8a935bc55e830481073e377d09cdf66d)) (thanks **Jelte Fennema**!) - Updates so that directory doesn't get overridden [#78](https://github.com/miguelgrinberg/flask-migrate/issues/78) where directory gets overridden if it is not explicitly specified in init_app. This fix allows it to be set when the `Migrate` object is initialized and not automatically get overridden when the `init_app` is called. This is a non-breaking change. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/0c9a2cbe35953cdabca571f402883c202ddfa09f)) (thanks **Tim Martin**!) **Release 1.5.1** - 2015-08-24 - Do not generate a migration if no schema changes are found ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/626c83feb49f571c2a4468a8fc9f81a44eecc451)) - Fix the merge command by allowing more than one argument. [#74](https://github.com/miguelgrinberg/flask-migrate/issues/74) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/9c62c963c0e142a40233dd6dde17925cdc34ea9d)) (thanks **Kevin Dwyer**!) **Relese 1.5.0** - 2015-08-01 - Make the multi-database configuration fully automatic ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ed1606c02dd3e57580d853db6ebe66804a5f0ceb)) - Add sane default for `db downgrade --sql` [#71](https://github.com/miguelgrinberg/flask-migrate/issues/71) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/01a2e701259e7792c82b2173587750efe5523877)) (thanks **Anthony Miyaguchi**!) - Add support for multiple databases migration [#70](https://github.com/miguelgrinberg/flask-migrate/issues/70) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/07737da36faf103987a9aa1df1e39ab8259b5181)) (thanks **Nan Jiang**!) - Added support for -x option ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/a2ff9d668393e4d2da555dc145ee80c065ac932a)) (thanks **jesse**!) **release 1.4.0** - 2015-04-27 - Pass custom Alembic configuration options, such as compare_type. Also the tests have been restructured for clarity. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ee32ae4db5f406508dac0b93f1dacb2b8d05a5f9)) **release 1.3.1** - 2015-03-20 - Update __init__.py alembic version now includes parts that are not integers (e.g., 0.7.5.post1). This change will prevent the code from trying to convert non-integer values to integers. ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/49d4d99897a8756c0fa732d879b29900e6adcef4)) (thanks **pjryan126**!) - Added syntax highlighting to README [#44](https://github.com/miguelgrinberg/flask-migrate/issues/44) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8cef3eb124c4df443b32cc33ddfeb97a3a810c05)) (thanks **Bulat Bochkariov**!) **version 1.3.0** - 2014-12-01 - new commands and options introduced with Alembic 0.7 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d848cb43da247259948270cb0745a99c2e118866)) - pep8 changes ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/71ff1d717be124d5a1c6c930dc911a5635e323e0)) - Updated docs: add installation [#37](https://github.com/miguelgrinberg/flask-migrate/issues/37) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/aca0ce8381fbb083a3eae9b0e1d60a3de43a0be2)) (thanks **Mozillazg**!) - travis CI builds ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/8e8a4d018f9a0a148adef712b9227dab6c990d1b)) - travis configuration ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/5241108fdb1797a883bd1844f525e35081ceb199)) - Added Python 3 programming language support to setup.py ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d13b42bdce60db64ad56f43350f3cb15f5f7bbe7)) (thanks **Fotis Gimian**!) - Added travis configuration ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/917b2577e58c35b03acca0fcf8f2f09e7686975f)) (thanks **Fotis Gimian**!) - Added test-related temp_folder to gitignore list ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ccc87167c68759b4eded529ca2335f2743f7bb4f)) (thanks **Fotis Gimian**!) - Repaired tests to correctly run under Python 3.3 ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/d4451fddddd951cdb144320e98162ba8616f1109)) (thanks **Fotis Gimian**!) **release 1.2.0** - 2014-01-19 - Added the branches command [#15](https://github.com/miguelgrinberg/flask-migrate/issues/15) ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/b9913c6458adba1e511ee86fd5a7291214f2eb9f)) (thanks **Bogdan Gaza**!) - added tests directory to tarball ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/9896e370f98bb62d9a363fea564d6758d2566263)) **release 1.1.0** - 2013-12-20 - [#12](https://github.com/miguelgrinberg/flask-migrate/issues/12): pass a default migrations directory in the Migrate constructor ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/189dbb5600c164147751453e72a1c8bb8e4229c3)) - Merge branch 'master' of github.com:miguelgrinberg/Flask-Migrate ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/3d364a81edacda81ccee60a33616ba15d47b5c27)) - pass revision range to history command ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/790442da2f9fa8168c6c0aa837ed4a1505980059)) (thanks **David Lord**!) - scripting interface ([commit](https://github.com/miguelgrinberg/flask-migrate/commit/ba6a0904616b701cc48f066fe3fca18a432b7f10)) **release 1.0.0** - 2013-12-03 - First official release! flask-migrate-4.0.7/LICENSE000066400000000000000000000020721457365025700152740ustar00rootroot00000000000000The 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-4.0.7/MANIFEST.in000066400000000000000000000005141457365025700160240ustar00rootroot00000000000000include README.md LICENSE tox.ini recursive-include docs * recursive-exclude docs/_build * recursive-include tests * exclude **/*.pyc include src/flask_migrate/templates/flask/* include src/flask_migrate/templates/flask-multidb/* include src/flask_migrate/templates/aioflask/* include src/flask_migrate/templates/aioflask-multidb/* flask-migrate-4.0.7/README.md000066400000000000000000000044301457365025700155460ustar00rootroot00000000000000Flask-Migrate ============= [![Build status](https://github.com/miguelgrinberg/flask-migrate/workflows/build/badge.svg)](https://github.com/miguelgrinberg/flask-migrate/actions) Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are provided as command-line arguments under the `flask db` command. Installation ------------ Install Flask-Migrate with `pip`: pip install Flask-Migrate Example ------- This is an example application that handles database migrations through Flask-Migrate: ```python from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' db = SQLAlchemy(app) migrate = Migrate(app, db) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) ``` With the above application you can create the database or enable migrations if the database already exists with the following command: $ flask db init Note that the `FLASK_APP` environment variable must be set according to the Flask documentation for this command to work. 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: $ flask 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: $ flask 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: $ flask db --help Resources --------- - [Documentation](http://flask-migrate.readthedocs.io/en/latest/) - [pypi](https://pypi.python.org/pypi/Flask-Migrate) - [Change Log](https://github.com/miguelgrinberg/Flask-Migrate/blob/master/CHANGES.md) flask-migrate-4.0.7/docs/000077500000000000000000000000001457365025700152165ustar00rootroot00000000000000flask-migrate-4.0.7/docs/Makefile000066400000000000000000000011041457365025700166520ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)flask-migrate-4.0.7/docs/conf.py000066400000000000000000000125141457365025700165200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'Flask-Migrate' copyright = '2019, Miguel Grinberg' author = 'Miguel Grinberg' # The short X.Y version version = '' # The full version, including alpha/beta/rc tags release = '' # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = None # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = { 'github_user': 'miguelgrinberg', 'github_repo': 'flask-migrate', 'github_banner': True, 'github_button': True, 'github_type': 'star', 'fixed_sidebar': True, } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # html_sidebars = { '**': [ 'about.html', 'localtoc.html', 'searchbox.html' ] } # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'Flask-Migratedoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'Flask-Migrate.tex', 'Flask-Migrate Documentation', 'Miguel Grinberg', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'flask-migrate', 'Flask-Migrate Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'Flask-Migrate', 'Flask-Migrate Documentation', author, 'Flask-Migrate', 'One line description of project.', 'Miscellaneous'), ] # -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] flask-migrate-4.0.7/docs/index.rst000066400000000000000000000305761457365025700170720ustar00rootroot00000000000000.. Flask-Migrate documentation master file, created by sphinx-quickstart on Fri Jul 26 14:48:13 2013. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Flask-Migrate ============= **Flask-Migrate** is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are made available through the Flask command-line interface. Why Use Flask-Migrate vs. Alembic Directly? ------------------------------------------- Flask-Migrate is an extension that configures Alembic in the proper way to work with your Flask and Flask-SQLAlchemy application. In terms of the actual database migrations, everything is handled by Alembic so you get exactly the same functionality. Installation ------------ Install Flask-Migrate with `pip`:: pip install Flask-Migrate Example ------- This is an example application that handles database migrations through Flask-Migrate:: from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' db = SQLAlchemy(app) migrate = Migrate(app, db) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) With the above application you can create a migration repository with the following command:: $ flask 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:: $ flask db migrate -m "Initial migration." The migration script needs to be reviewed and edited, as Alembic is not always able to detect every change you make to your models. In particular, Alembic is currently unable to detect table name changes, column name changes, or anonymously named constraints. A detailed summary of limitations can be found in the `Alembic autogenerate documentation `_. Once finalized, the migration script also needs to be added to version control. Then you can apply the changes described by the migration script to your database:: $ flask db upgrade 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:: $ flask db --help Note that the application script must be set in the ``FLASK_APP`` environment variable for all the above commands to work, as required by the ``flask`` command. If the ``db`` command group name is inconvenient, it can be changed to a different with the ``command`` argument passed to the ``Migrate`` class:: migrate = Migrate(app, db, command='migrate') Alembic Configuration Options ----------------------------- Starting with version 4.0, Flask-Migrate automatically enables the following options that are disabled by default in Alembic: - ``compare_type=True``: This option configures the automatic migration generation subsystem to detect column type changes. - ``render_as_batch=True``: This option generates migration scripts using `batch mode `_, an operational mode that works around limitations of many ``ALTER`` commands in the SQLite database by implementing a "move and copy" workflow. Enabling this mode should make no difference when working with other databases. To manually configure these or `other Alembic options `_, pass them as keyword arguments to the ``Migrate`` constructor. Example:: migrate = Migrate(app, db, render_as_batch=False) Configuration Callbacks ----------------------- Sometimes applications need to dynamically insert their own settings into the Alembic configuration. A function decorated with the ``configure`` callback will be invoked after the configuration is read, and before it is applied. The function can modify the configuration object, or replace it with a different one. :: @migrate.configure def configure_alembic(config): # modify config object return config Multiple configuration callbacks can be defined simply by decorating multiple functions. The order in which multiple callbacks are invoked is undetermined. Multiple Database Support ------------------------- Flask-Migrate can integrate with the `binds `_ feature of Flask-SQLAlchemy, making it possible to track migrations to multiple databases associated with an application. To create a multiple database migration repository, add the ``--multidb`` argument to the ``init`` command:: $ flask db init --multidb With this command, the migration repository will be set up to track migrations on your main database, and on any additional databases defined in the ``SQLALCHEMY_BINDS`` configuration option. Command Reference ----------------- Flask-Migrate exposes one class called ``Migrate``. This class contains all the functionality of the extension. The following example initializes the extension with the standard Flask command-line interface:: from flask_migrate import Migrate migrate = Migrate(app, db) The two arguments to ``Migrate`` are the application instance and the Flask-SQLAlchemy database instance. The ``Migrate`` constructor also takes additional keyword arguments, which are passed to Alembic's ``EnvironmentContext.configure()`` method. As is standard for all Flask extensions, Flask-Migrate can be initialized using the ``init_app`` method as well:: from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate db = SQLAlchemy() migrate = Migrate() def create_app(): """Application-factory pattern""" ... ... db.init_app(app) migrate.init_app(app, db) ... ... return app After the extension is initialized, a ``db`` group will be added to the command-line options with several sub-commands. Below is a list of the available sub-commands: - ``flask db --help`` Shows a list of available commands. - ``flask db list-templates`` Shows a list of available database repository templates. - ``flask db init [--multidb] [--template TEMPLATE] [--package]`` Initializes migration support for the application. The optional ``--multidb`` enables migrations for multiple databases configured as `Flask-SQLAlchemy binds `_. The ``--template`` option allows you to explicitly select a database repository template, either from the stock templates provided by this package, or a custom one, given as a path to the template directory. The ``--package`` option tells Alembic to add ``__init__.py`` files in the migrations and versions directories. - ``flask db revision [--message MESSAGE] [--autogenerate] [--sql] [--head HEAD] [--splice] [--branch-label BRANCH_LABEL] [--version-path VERSION_PATH] [--rev-id REV_ID]`` Creates an empty revision script. The script needs to be edited manually with the upgrade and downgrade changes. See `Alembic's documentation `_ for instructions on how to write migration scripts. An optional migration message can be included. - ``flask db migrate [--message MESSAGE] [--sql] [--head HEAD] [--splice] [--branch-label BRANCH_LABEL] [--version-path VERSION_PATH] [--rev-id REV_ID]`` Equivalent to ``revision --autogenerate``. The migration script is populated with changes detected automatically. The generated script should to be reviewed and edited as not all types of changes can be detected automatically. This command does not make any changes to the database, just creates the revision script. - ``flask db check`` Checks that a ``migrate`` command would not generate any changes. If pending changes are detected, the command exits with a non-zero status code. - ``flask db edit `` Edit a revision script using $EDITOR. - ``flask db upgrade [--sql] [--tag TAG] `` Upgrades the database. If ``revision`` isn't given then ``"head"`` is assumed. - ``flask db downgrade [--sql] [--tag TAG] `` Downgrades the database. If ``revision`` isn't given then ``-1`` is assumed. - ``flask db stamp [--sql] [--tag TAG] `` Sets the revision in the database to the one given as an argument, without performing any migrations. - ``flask db current [--verbose]`` Shows the current revision of the database. - ``flask db history [--rev-range REV_RANGE] [--verbose]`` Shows the list of migrations. If a range isn't given then the entire history is shown. - ``flask db show `` Show the revision denoted by the given symbol. - ``flask db merge [--message MESSAGE] [--branch-label BRANCH_LABEL] [--rev-id REV_ID] `` Merge two revisions together. Creates a new revision file. - ``flask db heads [--verbose] [--resolve-dependencies]`` Show current available heads in the revision script directory. - ``flask db branches [--verbose]`` Show current branch points. Notes: - All commands take one or more ``--x-arg ARG=VALUE`` or ``-x ARG=VALUE`` options with custom arguments that can be used in ``env.py``. - All commands take a ``--directory DIRECTORY`` option that points to the directory containing the migration scripts. If this argument is omitted the directory used is ``migrations``. - The default directory can also be specified as a ``directory`` argument to the ``Migrate`` constructor. - The ``--sql`` option present in several commands performs an 'offline' mode migration. Instead of executing the database commands the SQL statements that need to be executed are printed to the console. - Detailed documentation on these commands can be found in the `Alembic's command reference page `_. API Reference ------------- The commands exposed by Flask-Migrate's command-line interface can also be accessed programmatically by importing the functions from module ``flask_migrate``. The available functions are: - ``init(directory='migrations', multidb=False)`` Initializes migration support for the application. - ``revision(directory='migrations', message=None, autogenerate=False, sql=False, head='head', splice=False, branch_label=None, version_path=None, rev_id=None)`` Creates an empty revision script. - ``migrate(directory='migrations', message=None, sql=False, head='head', splice=False, branch_label=None, version_path=None, rev_id=None)`` Creates an automatic revision script. - ``edit(directory='migrations', revision='head')`` Edit revision script(s) using $EDITOR. - ``merge(directory='migrations', revisions='', message=None, branch_label=None, rev_id=None)`` Merge two revisions together. Creates a new migration file. - ``upgrade(directory='migrations', revision='head', sql=False, tag=None)`` Upgrades the database. - ``downgrade(directory='migrations', revision='-1', sql=False, tag=None)`` Downgrades the database. - ``show(directory='migrations', revision='head')`` Show the revision denoted by the given symbol. - ``history(directory='migrations', rev_range=None, verbose=False)`` Shows the list of migrations. If a range isn't given then the entire history is shown. - ``heads(directory='migrations', verbose=False, resolve_dependencies=False)`` Show current available heads in the script directory. - ``branches(directory='migrations', verbose=False)`` Show current branch points - ``current(directory='migrations', verbose=False, head_only=False)`` Shows the current revision of the database. - ``stamp(directory='migrations', revision='head', sql=False, tag=None)`` Sets the revision in the database to the one given as an argument, without performing any migrations. Notes: - These commands will invoke the same functionality that runs from the command-line, including output to the terminal. The logging configuration of the process will be overriden by Alembic according to the contents of the alembic.ini file. - For greater scripting flexibility you can also use the API exposed by Alembic directly. flask-migrate-4.0.7/docs/make.bat000066400000000000000000000014231457365025700166230ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% :end popd flask-migrate-4.0.7/pyproject.toml000066400000000000000000000021041457365025700171770ustar00rootroot00000000000000[project] name = "Flask-Migrate" version = "4.0.7" authors = [ { name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com" }, ] description = "SQLAlchemy database migrations for Flask applications using Alembic." classifiers = [ "Environment :: Web Environment", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ] requires-python = ">=3.6" dependencies = [ "Flask >= 0.9", "Flask-SQLAlchemy >= 1.0", "alembic >= 1.9.0", ] [project.license] text = "MIT" [project.readme] file = "README.md" content-type = "text/markdown" [project.urls] Homepage = "https://github.com/miguelgrinberg/flask-migrate" "Bug Tracker" = "https://github.com/miguelgrinberg/flask-migrate/issues" [tool.setuptools] zip-safe = false include-package-data = true [tool.setuptools.package-dir] "" = "src" [tool.setuptools.packages.find] where = [ "src", ] namespaces = true [build-system] requires = [ "setuptools>=61.2", ] build-backend = "setuptools.build_meta" flask-migrate-4.0.7/src/000077500000000000000000000000001457365025700150555ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/000077500000000000000000000000001457365025700176655ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/__init__.py000066400000000000000000000235421457365025700220040ustar00rootroot00000000000000import argparse from functools import wraps import logging import os import sys from flask import current_app, g from alembic import __version__ as __alembic_version__ from alembic.config import Config as AlembicConfig from alembic import command from alembic.util import CommandError alembic_version = tuple([int(v) for v in __alembic_version__.split('.')[0:3]]) log = logging.getLogger(__name__) class _MigrateConfig(object): def __init__(self, migrate, db, **kwargs): self.migrate = migrate self.db = db self.directory = migrate.directory self.configure_args = kwargs @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 Config(AlembicConfig): def __init__(self, *args, **kwargs): self.template_directory = kwargs.pop('template_directory', None) super().__init__(*args, **kwargs) def get_template_directory(self): if self.template_directory: return self.template_directory package_dir = os.path.abspath(os.path.dirname(__file__)) return os.path.join(package_dir, 'templates') class Migrate(object): def __init__(self, app=None, db=None, directory='migrations', command='db', compare_type=True, render_as_batch=True, **kwargs): self.configure_callbacks = [] self.db = db self.command = command self.directory = str(directory) self.alembic_ctx_kwargs = kwargs self.alembic_ctx_kwargs['compare_type'] = compare_type self.alembic_ctx_kwargs['render_as_batch'] = render_as_batch if app is not None and db is not None: self.init_app(app, db, directory) def init_app(self, app, db=None, directory=None, command=None, compare_type=None, render_as_batch=None, **kwargs): self.db = db or self.db self.command = command or self.command self.directory = str(directory or self.directory) self.alembic_ctx_kwargs.update(kwargs) if compare_type is not None: self.alembic_ctx_kwargs['compare_type'] = compare_type if render_as_batch is not None: self.alembic_ctx_kwargs['render_as_batch'] = render_as_batch if not hasattr(app, 'extensions'): app.extensions = {} app.extensions['migrate'] = _MigrateConfig( self, self.db, **self.alembic_ctx_kwargs) from flask_migrate.cli import db as db_cli_group app.cli.add_command(db_cli_group, name=self.command) def configure(self, f): self.configure_callbacks.append(f) return f def call_configure_callbacks(self, config): for f in self.configure_callbacks: config = f(config) return config def get_config(self, directory=None, x_arg=None, opts=None): if directory is None: directory = self.directory directory = str(directory) config = Config(os.path.join(directory, 'alembic.ini')) config.set_main_option('script_location', directory) if config.cmd_opts is None: config.cmd_opts = argparse.Namespace() for opt in opts or []: setattr(config.cmd_opts, opt, True) if not hasattr(config.cmd_opts, 'x'): setattr(config.cmd_opts, 'x', []) for x in getattr(g, 'x_arg', []): config.cmd_opts.x.append(x) if x_arg is not None: if isinstance(x_arg, list) or isinstance(x_arg, tuple): for x in x_arg: config.cmd_opts.x.append(x) else: config.cmd_opts.x.append(x_arg) return self.call_configure_callbacks(config) def catch_errors(f): @wraps(f) def wrapped(*args, **kwargs): try: f(*args, **kwargs) except (CommandError, RuntimeError) as exc: log.error('Error: ' + str(exc)) sys.exit(1) return wrapped @catch_errors def list_templates(): """List available templates.""" config = Config() config.print_stdout("Available templates:\n") for tempname in sorted(os.listdir(config.get_template_directory())): with open( os.path.join(config.get_template_directory(), tempname, "README") ) as readme: synopsis = next(readme).strip() config.print_stdout("%s - %s", tempname, synopsis) @catch_errors def init(directory=None, multidb=False, template=None, package=False): """Creates a new migration repository""" if directory is None: directory = current_app.extensions['migrate'].directory template_directory = None if template is not None and ('/' in template or '\\' in template): template_directory, template = os.path.split(template) config = Config(template_directory=template_directory) config.set_main_option('script_location', directory) config.config_file_name = os.path.join(directory, 'alembic.ini') config = current_app.extensions['migrate'].\ migrate.call_configure_callbacks(config) if multidb and template is None: template = 'flask-multidb' elif template is None: template = 'flask' command.init(config, directory, template=template, package=package) @catch_errors def revision(directory=None, message=None, autogenerate=False, sql=False, head='head', splice=False, branch_label=None, version_path=None, rev_id=None): """Create a new revision file.""" opts = ['autogenerate'] if autogenerate else None config = current_app.extensions['migrate'].migrate.get_config( directory, opts=opts) command.revision(config, message, autogenerate=autogenerate, sql=sql, head=head, splice=splice, branch_label=branch_label, version_path=version_path, rev_id=rev_id) @catch_errors def migrate(directory=None, message=None, sql=False, head='head', splice=False, branch_label=None, version_path=None, rev_id=None, x_arg=None): """Alias for 'revision --autogenerate'""" config = current_app.extensions['migrate'].migrate.get_config( directory, opts=['autogenerate'], x_arg=x_arg) command.revision(config, message, autogenerate=True, sql=sql, head=head, splice=splice, branch_label=branch_label, version_path=version_path, rev_id=rev_id) @catch_errors def edit(directory=None, revision='current'): """Edit current revision.""" if alembic_version >= (0, 8, 0): config = current_app.extensions['migrate'].migrate.get_config( directory) command.edit(config, revision) else: raise RuntimeError('Alembic 0.8.0 or greater is required') @catch_errors def merge(directory=None, revisions='', message=None, branch_label=None, rev_id=None): """Merge two revisions together. Creates a new migration file""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.merge(config, revisions, message=message, branch_label=branch_label, rev_id=rev_id) @catch_errors def upgrade(directory=None, revision='head', sql=False, tag=None, x_arg=None): """Upgrade to a later version""" config = current_app.extensions['migrate'].migrate.get_config(directory, x_arg=x_arg) command.upgrade(config, revision, sql=sql, tag=tag) @catch_errors def downgrade(directory=None, revision='-1', sql=False, tag=None, x_arg=None): """Revert to a previous version""" config = current_app.extensions['migrate'].migrate.get_config(directory, x_arg=x_arg) if sql and revision == '-1': revision = 'head:-1' command.downgrade(config, revision, sql=sql, tag=tag) @catch_errors def show(directory=None, revision='head'): """Show the revision denoted by the given symbol.""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.show(config, revision) @catch_errors def history(directory=None, rev_range=None, verbose=False, indicate_current=False): """List changeset scripts in chronological order.""" config = current_app.extensions['migrate'].migrate.get_config(directory) if alembic_version >= (0, 9, 9): command.history(config, rev_range, verbose=verbose, indicate_current=indicate_current) else: command.history(config, rev_range, verbose=verbose) @catch_errors def heads(directory=None, verbose=False, resolve_dependencies=False): """Show current available heads in the script directory""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.heads(config, verbose=verbose, resolve_dependencies=resolve_dependencies) @catch_errors def branches(directory=None, verbose=False): """Show current branch points""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.branches(config, verbose=verbose) @catch_errors def current(directory=None, verbose=False): """Display the current revision for each database.""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.current(config, verbose=verbose) @catch_errors def stamp(directory=None, revision='head', sql=False, tag=None, purge=False): """'stamp' the revision table with the given revision; don't run any migrations""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.stamp(config, revision, sql=sql, tag=tag, purge=purge) @catch_errors def check(directory=None): """Check if there are any new operations to migrate""" config = current_app.extensions['migrate'].migrate.get_config(directory) command.check(config) flask-migrate-4.0.7/src/flask_migrate/cli.py000066400000000000000000000247011457365025700210120ustar00rootroot00000000000000import click from flask import g from flask.cli import with_appcontext from flask_migrate import list_templates as _list_templates from flask_migrate import init as _init from flask_migrate import revision as _revision from flask_migrate import migrate as _migrate from flask_migrate import edit as _edit from flask_migrate import merge as _merge from flask_migrate import upgrade as _upgrade from flask_migrate import downgrade as _downgrade from flask_migrate import show as _show from flask_migrate import history as _history from flask_migrate import heads as _heads from flask_migrate import branches as _branches from flask_migrate import current as _current from flask_migrate import stamp as _stamp from flask_migrate import check as _check @click.group() @click.option('-x', '--x-arg', multiple=True, help='Additional arguments consumed by custom env.py scripts') @with_appcontext def db(x_arg): """Perform database migrations.""" g.x_arg = x_arg # these will be picked up by Migrate.get_config() @db.command() @with_appcontext def list_templates(): """List available templates.""" _list_templates() @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('--multidb', is_flag=True, help=('Support multiple databases')) @click.option('-t', '--template', default=None, help=('Repository template to use (default is "flask")')) @click.option('--package', is_flag=True, help=('Write empty __init__.py files to the environment and ' 'version locations')) @with_appcontext def init(directory, multidb, template, package): """Creates a new migration repository.""" _init(directory, multidb, template, package) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-m', '--message', default=None, help='Revision message') @click.option('--autogenerate', is_flag=True, help=('Populate revision script with candidate migration ' 'operations, based on comparison of database to model')) @click.option('--sql', is_flag=True, help=('Don\'t emit SQL to database - dump to standard output ' 'instead')) @click.option('--head', default='head', help=('Specify head revision or @head to base new ' 'revision on')) @click.option('--splice', is_flag=True, help=('Allow a non-head revision as the "head" to splice onto')) @click.option('--branch-label', default=None, help=('Specify a branch label to apply to the new revision')) @click.option('--version-path', default=None, help=('Specify specific path from config for version file')) @click.option('--rev-id', default=None, help=('Specify a hardcoded revision id instead of generating ' 'one')) @with_appcontext def revision(directory, message, autogenerate, sql, head, splice, branch_label, version_path, rev_id): """Create a new revision file.""" _revision(directory, message, autogenerate, sql, head, splice, branch_label, version_path, rev_id) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-m', '--message', default=None, help='Revision message') @click.option('--sql', is_flag=True, help=('Don\'t emit SQL to database - dump to standard output ' 'instead')) @click.option('--head', default='head', help=('Specify head revision or @head to base new ' 'revision on')) @click.option('--splice', is_flag=True, help=('Allow a non-head revision as the "head" to splice onto')) @click.option('--branch-label', default=None, help=('Specify a branch label to apply to the new revision')) @click.option('--version-path', default=None, help=('Specify specific path from config for version file')) @click.option('--rev-id', default=None, help=('Specify a hardcoded revision id instead of generating ' 'one')) @click.option('-x', '--x-arg', multiple=True, help='Additional arguments consumed by custom env.py scripts') @with_appcontext def migrate(directory, message, sql, head, splice, branch_label, version_path, rev_id, x_arg): """Autogenerate a new revision file (Alias for 'revision --autogenerate')""" _migrate(directory, message, sql, head, splice, branch_label, version_path, rev_id, x_arg) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.argument('revision', default='head') @with_appcontext def edit(directory, revision): """Edit a revision file""" _edit(directory, revision) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-m', '--message', default=None, help='Merge revision message') @click.option('--branch-label', default=None, help=('Specify a branch label to apply to the new revision')) @click.option('--rev-id', default=None, help=('Specify a hardcoded revision id instead of generating ' 'one')) @click.argument('revisions', nargs=-1) @with_appcontext def merge(directory, message, branch_label, rev_id, revisions): """Merge two revisions together, creating a new revision file""" _merge(directory, revisions, message, branch_label, rev_id) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('--sql', is_flag=True, help=('Don\'t emit SQL to database - dump to standard output ' 'instead')) @click.option('--tag', default=None, help=('Arbitrary "tag" name - can be used by custom env.py ' 'scripts')) @click.option('-x', '--x-arg', multiple=True, help='Additional arguments consumed by custom env.py scripts') @click.argument('revision', default='head') @with_appcontext def upgrade(directory, sql, tag, x_arg, revision): """Upgrade to a later version""" _upgrade(directory, revision, sql, tag, x_arg) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('--sql', is_flag=True, help=('Don\'t emit SQL to database - dump to standard output ' 'instead')) @click.option('--tag', default=None, help=('Arbitrary "tag" name - can be used by custom env.py ' 'scripts')) @click.option('-x', '--x-arg', multiple=True, help='Additional arguments consumed by custom env.py scripts') @click.argument('revision', default='-1') @with_appcontext def downgrade(directory, sql, tag, x_arg, revision): """Revert to a previous version""" _downgrade(directory, revision, sql, tag, x_arg) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.argument('revision', default='head') @with_appcontext def show(directory, revision): """Show the revision denoted by the given symbol.""" _show(directory, revision) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-r', '--rev-range', default=None, help='Specify a revision range; format is [start]:[end]') @click.option('-v', '--verbose', is_flag=True, help='Use more verbose output') @click.option('-i', '--indicate-current', is_flag=True, help=('Indicate current version (Alembic 0.9.9 or greater is ' 'required)')) @with_appcontext def history(directory, rev_range, verbose, indicate_current): """List changeset scripts in chronological order.""" _history(directory, rev_range, verbose, indicate_current) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-v', '--verbose', is_flag=True, help='Use more verbose output') @click.option('--resolve-dependencies', is_flag=True, help='Treat dependency versions as down revisions') @with_appcontext def heads(directory, verbose, resolve_dependencies): """Show current available heads in the script directory""" _heads(directory, verbose, resolve_dependencies) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-v', '--verbose', is_flag=True, help='Use more verbose output') @with_appcontext def branches(directory, verbose): """Show current branch points""" _branches(directory, verbose) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('-v', '--verbose', is_flag=True, help='Use more verbose output') @with_appcontext def current(directory, verbose): """Display the current revision for each database.""" _current(directory, verbose) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @click.option('--sql', is_flag=True, help=('Don\'t emit SQL to database - dump to standard output ' 'instead')) @click.option('--tag', default=None, help=('Arbitrary "tag" name - can be used by custom env.py ' 'scripts')) @click.option('--purge', is_flag=True, help=('Delete the version in the alembic_version table before ' 'stamping')) @click.argument('revision', default='head') @with_appcontext def stamp(directory, sql, tag, revision, purge): """'stamp' the revision table with the given revision; don't run any migrations""" _stamp(directory, revision, sql, tag, purge) @db.command() @click.option('-d', '--directory', default=None, help=('Migration script directory (default is "migrations")')) @with_appcontext def check(directory): """Check if there are any new operations to migrate""" _check(directory) flask-migrate-4.0.7/src/flask_migrate/templates/000077500000000000000000000000001457365025700216635ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/templates/aioflask-multidb/000077500000000000000000000000001457365025700251125ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/templates/aioflask-multidb/README000066400000000000000000000000531457365025700257700ustar00rootroot00000000000000Multi-database configuration for aioflask. flask-migrate-4.0.7/src/flask_migrate/templates/aioflask-multidb/alembic.ini.mako000066400000000000000000000015311457365025700301350ustar00rootroot00000000000000# 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,flask_migrate [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 [logger_flask_migrate] level = INFO handlers = qualname = flask_migrate [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-4.0.7/src/flask_migrate/templates/aioflask-multidb/env.py000066400000000000000000000146551457365025700262670ustar00rootroot00000000000000import asyncio import logging from logging.config import fileConfig from sqlalchemy import MetaData from flask import current_app from alembic import context USE_TWOPHASE = False # 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) logger = logging.getLogger('alembic.env') def get_engine(bind_key=None): try: # this works with Flask-SQLAlchemy<3 and Alchemical return current_app.extensions['migrate'].db.get_engine(bind=bind_key) except (TypeError, AttributeError): # this works with Flask-SQLAlchemy>=3 return current_app.extensions['migrate'].db.engines.get(bind_key) def get_engine_url(bind_key=None): try: return get_engine(bind_key).url.render_as_string( hide_password=False).replace('%', '%%') except AttributeError: return str(get_engine(bind_key).url).replace('%', '%%') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option('sqlalchemy.url', get_engine_url()) bind_names = [] if current_app.config.get('SQLALCHEMY_BINDS') is not None: bind_names = list(current_app.config['SQLALCHEMY_BINDS'].keys()) else: get_bind_names = getattr(current_app.extensions['migrate'].db, 'bind_names', None) if get_bind_names: bind_names = get_bind_names() for bind in bind_names: context.config.set_section_option( bind, "sqlalchemy.url", get_engine_url(bind_key=bind)) target_db = current_app.extensions['migrate'].db # 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 get_metadata(bind): """Return the metadata for a bind.""" if bind == '': bind = None if hasattr(target_db, 'metadatas'): return target_db.metadatas[bind] # legacy, less flexible implementation m = MetaData() for t in target_db.metadata.tables.values(): if t.info.get('bind_key') == bind: t.tometadata(m) return m 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. """ # for the --sql use case, run migrations for each URL into # individual files. engines = { '': { 'url': context.config.get_main_option('sqlalchemy.url') } } for name in bind_names: engines[name] = rec = {} rec['url'] = context.config.get_section_option(name, "sqlalchemy.url") for name, rec in engines.items(): logger.info("Migrating database %s" % (name or '')) file_ = "%s.sql" % name logger.info("Writing output to %s" % file_) with open(file_, 'w') as buffer: context.configure( url=rec['url'], output_buffer=buffer, target_metadata=get_metadata(name), literal_binds=True, ) with context.begin_transaction(): context.run_migrations(engine_name=name) def do_run_migrations(_, engines): # this callback is used to prevent an auto-migration from being generated # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if len(script.upgrade_ops_list) >= len(bind_names) + 1: empty = True for upgrade_ops in script.upgrade_ops_list: if not upgrade_ops.is_empty(): empty = False if empty: directives[:] = [] logger.info('No changes in schema detected.') conf_args = current_app.extensions['migrate'].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives for name, rec in engines.items(): rec['sync_connection'] = conn = rec['connection']._sync_connection() if USE_TWOPHASE: rec['transaction'] = conn.begin_twophase() else: rec['transaction'] = conn.begin() try: for name, rec in engines.items(): logger.info("Migrating database %s" % (name or '')) context.configure( connection=rec['sync_connection'], upgrade_token="%s_upgrades" % name, downgrade_token="%s_downgrades" % name, target_metadata=get_metadata(name), **conf_args ) context.run_migrations(engine_name=name) if USE_TWOPHASE: for rec in engines.values(): rec['transaction'].prepare() for rec in engines.values(): rec['transaction'].commit() except: # noqa: E722 for rec in engines.values(): rec['transaction'].rollback() raise finally: for rec in engines.values(): rec['sync_connection'].close() async 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. """ # for the direct-to-DB use case, start a transaction on all # engines, then run all migrations, then commit all transactions. engines = { '': {'engine': get_engine()} } for name in bind_names: engines[name] = rec = {} rec['engine'] = get_engine(bind_key=name) for name, rec in engines.items(): engine = rec['engine'] rec['connection'] = await engine.connect().start() await engines['']['connection'].run_sync(do_run_migrations, engines) for rec in engines.values(): await rec['connection'].close() if context.is_offline_mode(): run_migrations_offline() else: asyncio.get_event_loop().run_until_complete(run_migrations_online()) flask-migrate-4.0.7/src/flask_migrate/templates/aioflask-multidb/script.py.mako000066400000000000000000000023361457365025700277220ustar00rootroot00000000000000<%! import re %>"""${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(engine_name): globals()["upgrade_%s" % engine_name]() def downgrade(engine_name): globals()["downgrade_%s" % engine_name]() <% from flask import current_app bind_names = [] if current_app.config.get('SQLALCHEMY_BINDS') is not None: bind_names = list(current_app.config['SQLALCHEMY_BINDS'].keys()) else: get_bind_names = getattr(current_app.extensions['migrate'].db, 'bind_names', None) if get_bind_names: bind_names = get_bind_names() db_names = [''] + bind_names %> ## generate an "upgrade_() / downgrade_()" function ## for each database name in the ini file. % for db_name in db_names: def upgrade_${db_name}(): ${context.get("%s_upgrades" % db_name, "pass")} def downgrade_${db_name}(): ${context.get("%s_downgrades" % db_name, "pass")} % endfor flask-migrate-4.0.7/src/flask_migrate/templates/aioflask/000077500000000000000000000000001457365025700234545ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/templates/aioflask/README000066400000000000000000000000541457365025700243330ustar00rootroot00000000000000Single-database configuration for aioflask. flask-migrate-4.0.7/src/flask_migrate/templates/aioflask/alembic.ini.mako000066400000000000000000000015311457365025700264770ustar00rootroot00000000000000# 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,flask_migrate [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 [logger_flask_migrate] level = INFO handlers = qualname = flask_migrate [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-4.0.7/src/flask_migrate/templates/aioflask/env.py000066400000000000000000000066261457365025700246300ustar00rootroot00000000000000import asyncio import logging from logging.config import fileConfig from flask import current_app 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) logger = logging.getLogger('alembic.env') def get_engine(): try: # this works with Flask-SQLAlchemy<3 and Alchemical return current_app.extensions['migrate'].db.get_engine() except (TypeError, AttributeError): # this works with Flask-SQLAlchemy>=3 return current_app.extensions['migrate'].db.engine def get_engine_url(): try: return get_engine().url.render_as_string(hide_password=False).replace( '%', '%%') except AttributeError: return str(get_engine().url).replace('%', '%%') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option('sqlalchemy.url', get_engine_url()) target_db = current_app.extensions['migrate'].db # 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 get_metadata(): if hasattr(target_db, 'metadatas'): return target_db.metadatas[None] return target_db.metadata 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=get_metadata(), literal_binds=True ) with context.begin_transaction(): context.run_migrations() def do_run_migrations(connection): # this callback is used to prevent an auto-migration from being generated # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] logger.info('No changes in schema detected.') conf_args = current_app.extensions['migrate'].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives context.configure( connection=connection, target_metadata=get_metadata(), **conf_args ) with context.begin_transaction(): context.run_migrations() async 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 = get_engine() async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) if context.is_offline_mode(): run_migrations_offline() else: asyncio.get_event_loop().run_until_complete(run_migrations_online()) flask-migrate-4.0.7/src/flask_migrate/templates/aioflask/script.py.mako000066400000000000000000000007561457365025700262700ustar00rootroot00000000000000"""${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"} flask-migrate-4.0.7/src/flask_migrate/templates/flask-multidb/000077500000000000000000000000001457365025700244215ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/templates/flask-multidb/README000066400000000000000000000000501457365025700252740ustar00rootroot00000000000000Multi-database configuration for Flask. flask-migrate-4.0.7/src/flask_migrate/templates/flask-multidb/alembic.ini.mako000066400000000000000000000015311457365025700274440ustar00rootroot00000000000000# 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,flask_migrate [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 [logger_flask_migrate] level = INFO handlers = qualname = flask_migrate [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-4.0.7/src/flask_migrate/templates/flask-multidb/env.py000066400000000000000000000140561457365025700255710ustar00rootroot00000000000000import logging from logging.config import fileConfig from sqlalchemy import MetaData from flask import current_app from alembic import context USE_TWOPHASE = False # 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) logger = logging.getLogger('alembic.env') def get_engine(bind_key=None): try: # this works with Flask-SQLAlchemy<3 and Alchemical return current_app.extensions['migrate'].db.get_engine(bind=bind_key) except (TypeError, AttributeError): # this works with Flask-SQLAlchemy>=3 return current_app.extensions['migrate'].db.engines.get(bind_key) def get_engine_url(bind_key=None): try: return get_engine(bind_key).url.render_as_string( hide_password=False).replace('%', '%%') except AttributeError: return str(get_engine(bind_key).url).replace('%', '%%') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option('sqlalchemy.url', get_engine_url()) bind_names = [] if current_app.config.get('SQLALCHEMY_BINDS') is not None: bind_names = list(current_app.config['SQLALCHEMY_BINDS'].keys()) else: get_bind_names = getattr(current_app.extensions['migrate'].db, 'bind_names', None) if get_bind_names: bind_names = get_bind_names() for bind in bind_names: context.config.set_section_option( bind, "sqlalchemy.url", get_engine_url(bind_key=bind)) target_db = current_app.extensions['migrate'].db # 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 get_metadata(bind): """Return the metadata for a bind.""" if bind == '': bind = None if hasattr(target_db, 'metadatas'): return target_db.metadatas[bind] # legacy, less flexible implementation m = MetaData() for t in target_db.metadata.tables.values(): if t.info.get('bind_key') == bind: t.tometadata(m) return m 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. """ # for the --sql use case, run migrations for each URL into # individual files. engines = { '': { 'url': context.config.get_main_option('sqlalchemy.url') } } for name in bind_names: engines[name] = rec = {} rec['url'] = context.config.get_section_option(name, "sqlalchemy.url") for name, rec in engines.items(): logger.info("Migrating database %s" % (name or '')) file_ = "%s.sql" % name logger.info("Writing output to %s" % file_) with open(file_, 'w') as buffer: context.configure( url=rec['url'], output_buffer=buffer, target_metadata=get_metadata(name), literal_binds=True, ) with context.begin_transaction(): context.run_migrations(engine_name=name) 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. """ # this callback is used to prevent an auto-migration from being generated # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if len(script.upgrade_ops_list) >= len(bind_names) + 1: empty = True for upgrade_ops in script.upgrade_ops_list: if not upgrade_ops.is_empty(): empty = False if empty: directives[:] = [] logger.info('No changes in schema detected.') conf_args = current_app.extensions['migrate'].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives # for the direct-to-DB use case, start a transaction on all # engines, then run all migrations, then commit all transactions. engines = { '': {'engine': get_engine()} } for name in bind_names: engines[name] = rec = {} rec['engine'] = get_engine(bind_key=name) for name, rec in engines.items(): engine = rec['engine'] rec['connection'] = conn = engine.connect() if USE_TWOPHASE: rec['transaction'] = conn.begin_twophase() else: rec['transaction'] = conn.begin() try: for name, rec in engines.items(): logger.info("Migrating database %s" % (name or '')) context.configure( connection=rec['connection'], upgrade_token="%s_upgrades" % name, downgrade_token="%s_downgrades" % name, target_metadata=get_metadata(name), **conf_args ) context.run_migrations(engine_name=name) if USE_TWOPHASE: for rec in engines.values(): rec['transaction'].prepare() for rec in engines.values(): rec['transaction'].commit() except: # noqa: E722 for rec in engines.values(): rec['transaction'].rollback() raise finally: for rec in engines.values(): rec['connection'].close() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() flask-migrate-4.0.7/src/flask_migrate/templates/flask-multidb/script.py.mako000066400000000000000000000023361457365025700272310ustar00rootroot00000000000000<%! import re %>"""${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(engine_name): globals()["upgrade_%s" % engine_name]() def downgrade(engine_name): globals()["downgrade_%s" % engine_name]() <% from flask import current_app bind_names = [] if current_app.config.get('SQLALCHEMY_BINDS') is not None: bind_names = list(current_app.config['SQLALCHEMY_BINDS'].keys()) else: get_bind_names = getattr(current_app.extensions['migrate'].db, 'bind_names', None) if get_bind_names: bind_names = get_bind_names() db_names = [''] + bind_names %> ## generate an "upgrade_() / downgrade_()" function ## for each database name in the ini file. % for db_name in db_names: def upgrade_${db_name}(): ${context.get("%s_upgrades" % db_name, "pass")} def downgrade_${db_name}(): ${context.get("%s_downgrades" % db_name, "pass")} % endfor flask-migrate-4.0.7/src/flask_migrate/templates/flask/000077500000000000000000000000001457365025700227635ustar00rootroot00000000000000flask-migrate-4.0.7/src/flask_migrate/templates/flask/README000066400000000000000000000000511457365025700236370ustar00rootroot00000000000000Single-database configuration for Flask. flask-migrate-4.0.7/src/flask_migrate/templates/flask/alembic.ini.mako000066400000000000000000000015311457365025700260060ustar00rootroot00000000000000# 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,flask_migrate [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 [logger_flask_migrate] level = INFO handlers = qualname = flask_migrate [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-4.0.7/src/flask_migrate/templates/flask/env.py000066400000000000000000000064201457365025700241270ustar00rootroot00000000000000import logging from logging.config import fileConfig from flask import current_app 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) logger = logging.getLogger('alembic.env') def get_engine(): try: # this works with Flask-SQLAlchemy<3 and Alchemical return current_app.extensions['migrate'].db.get_engine() except (TypeError, AttributeError): # this works with Flask-SQLAlchemy>=3 return current_app.extensions['migrate'].db.engine def get_engine_url(): try: return get_engine().url.render_as_string(hide_password=False).replace( '%', '%%') except AttributeError: return str(get_engine().url).replace('%', '%%') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option('sqlalchemy.url', get_engine_url()) target_db = current_app.extensions['migrate'].db # 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 get_metadata(): if hasattr(target_db, 'metadatas'): return target_db.metadatas[None] return target_db.metadata 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=get_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. """ # this callback is used to prevent an auto-migration from being generated # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] logger.info('No changes in schema detected.') conf_args = current_app.extensions['migrate'].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives connectable = get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=get_metadata(), **conf_args ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() flask-migrate-4.0.7/src/flask_migrate/templates/flask/script.py.mako000066400000000000000000000007561457365025700255770ustar00rootroot00000000000000"""${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"} flask-migrate-4.0.7/tests/000077500000000000000000000000001457365025700154305ustar00rootroot00000000000000flask-migrate-4.0.7/tests/__init__.py000066400000000000000000000000001457365025700175270ustar00rootroot00000000000000flask-migrate-4.0.7/tests/app.py000077500000000000000000000012611457365025700165650ustar00rootroot00000000000000#!/bin/env python import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db, compare_type=False) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(256)) @app.cli.command() def add(): """Add test user.""" db.session.add(User(name='test')) db.session.commit() if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/app_compare_type1.py000077500000000000000000000010501457365025700214110ustar00rootroot00000000000000import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db, command='database') class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/app_compare_type2.py000077500000000000000000000010471457365025700214200ustar00rootroot00000000000000import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db, command='database') class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(10)) if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/app_custom_directory.py000077500000000000000000000012641457365025700222460ustar00rootroot00000000000000import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db, directory='temp_folder/temp_migrations') class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) @app.cli.command() def add(): """Add test user.""" db.session.add(User(name='test')) db.session.commit() if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/app_custom_directory_path.py000077500000000000000000000013231457365025700232560ustar00rootroot00000000000000import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from pathlib import Path basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db, directory=Path('temp_folder/temp_migrations')) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) @app.cli.command() def add(): """Add test user.""" db.session.add(User(name='test')) db.session.commit() if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/app_multidb.py000077500000000000000000000016621457365025700203120ustar00rootroot00000000000000#!/bin/env python import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join( basedir, 'app1.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_BINDS'] = { "db1": "sqlite:///" + os.path.join(basedir, "app2.db"), } db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) class Group(db.Model): __bind_key__ = 'db1' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) migrate = Migrate(app, db) @app.cli.command() def add(): """Add test users.""" db.session.add(User(name='test')) db.session.add(Group(name='group')) db.session.commit() if __name__ == '__main__': app.run() flask-migrate-4.0.7/tests/custom_template/000077500000000000000000000000001457365025700206355ustar00rootroot00000000000000flask-migrate-4.0.7/tests/custom_template/README000066400000000000000000000000211457365025700215060ustar00rootroot00000000000000Custom template. flask-migrate-4.0.7/tests/custom_template/alembic.ini.mako000066400000000000000000000014771457365025700236710ustar00rootroot00000000000000# Custom template [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,flask_migrate [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 [logger_flask_migrate] level = INFO handlers = qualname = flask_migrate [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-4.0.7/tests/custom_template/env.py000066400000000000000000000054341457365025700220050ustar00rootroot00000000000000# Custom template import logging from logging.config import fileConfig from flask import current_app 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) logger = logging.getLogger('alembic.env') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( 'sqlalchemy.url', str(current_app.extensions['migrate'].db.get_engine().url).replace( '%', '%%')) 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, 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. """ # this callback is used to prevent an auto-migration from being generated # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] logger.info('No changes in schema detected.') conf_args = current_app.extensions['migrate'].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives connectable = current_app.extensions['migrate'].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, **conf_args ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() flask-migrate-4.0.7/tests/custom_template/script.py.mako000066400000000000000000000010001457365025700234300ustar00rootroot00000000000000# Custom template """${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"} flask-migrate-4.0.7/tests/test_custom_template.py000066400000000000000000000045461457365025700222570ustar00rootroot00000000000000import os import shutil import unittest import subprocess import shlex def run_cmd(app, cmd): """Run a command and return a tuple with (stdout, stderr, exit_code)""" os.environ['FLASK_APP'] = app process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = process.communicate() print('\n$ ' + cmd) print(stdout.decode('utf-8')) print(stderr.decode('utf-8')) return stdout, stderr, process.wait() 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 try: shutil.rmtree('temp_folder') except OSError: pass def tearDown(self): try: os.remove('app.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass try: shutil.rmtree('temp_folder') except OSError: pass def test_alembic_version(self): from flask_migrate import alembic_version self.assertEqual(len(alembic_version), 3) for v in alembic_version: self.assertTrue(isinstance(v, int)) def test_migrate_upgrade(self): (o, e, s) = run_cmd('app.py', 'flask db init -t ./custom_template') self.assertTrue(s == 0) (o, e, s) = run_cmd('app.py', 'flask db migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app.py', 'flask db upgrade') self.assertTrue(s == 0) from .app import app, db, User with app.app_context(): db.engine.dispose() db.session.add(User(name='test')) db.session.commit() with open('migrations/README', 'rt') as f: assert f.readline().strip() == 'Custom template.' with open('migrations/alembic.ini', 'rt') as f: assert f.readline().strip() == '# Custom template' with open('migrations/env.py', 'rt') as f: assert f.readline().strip() == '# Custom template' with open('migrations/script.py.mako', 'rt') as f: assert f.readline().strip() == '# Custom template' flask-migrate-4.0.7/tests/test_migrate.py000066400000000000000000000075131457365025700204770ustar00rootroot00000000000000import os import shutil import unittest import subprocess import shlex def run_cmd(app, cmd): """Run a command and return a tuple with (stdout, stderr, exit_code)""" os.environ['FLASK_APP'] = app process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = process.communicate() print('\n$ ' + cmd) print(stdout.decode('utf-8')) print(stderr.decode('utf-8')) return stdout, stderr, process.wait() 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 try: shutil.rmtree('temp_folder') except OSError: pass def tearDown(self): try: os.remove('app.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass try: shutil.rmtree('temp_folder') except OSError: pass def atest_alembic_version(self): from flask_migrate import alembic_version self.assertEqual(len(alembic_version), 3) for v in alembic_version: self.assertTrue(isinstance(v, int)) def test_migrate_upgrade(self): (o, e, s) = run_cmd('app.py', 'flask db init') self.assertTrue(s == 0) (o, e, s) = run_cmd('app.py', 'flask db check') self.assertTrue(s != 0) (o, e, s) = run_cmd('app.py', 'flask db migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app.py', 'flask db check') self.assertTrue(s != 0) (o, e, s) = run_cmd('app.py', 'flask db upgrade') self.assertTrue(s == 0) (o, e, s) = run_cmd('app.py', 'flask db check') self.assertTrue(s == 0) from .app import app, db, User with app.app_context(): db.engine.dispose() db.session.add(User(name='test')) db.session.commit() def test_custom_directory(self): (o, e, s) = run_cmd('app_custom_directory.py', 'flask db init') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_custom_directory.py', 'flask db migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_custom_directory.py', 'flask db upgrade') self.assertTrue(s == 0) from .app_custom_directory import app, db, User with app.app_context(): db.engine.dispose() db.session.add(User(name='test')) db.session.commit() def test_custom_directory_path(self): (o, e, s) = run_cmd('app_custom_directory_path.py', 'flask db init') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_custom_directory_path.py', 'flask db migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_custom_directory_path.py', 'flask db upgrade') self.assertTrue(s == 0) from .app_custom_directory_path import app, db, User with app.app_context(): db.engine.dispose() db.session.add(User(name='test')) db.session.commit() def test_compare_type(self): (o, e, s) = run_cmd('app_compare_type1.py', 'flask database init') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_compare_type1.py', 'flask database migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_compare_type1.py', 'flask database upgrade') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_compare_type2.py', 'flask database migrate') self.assertTrue(s == 0) self.assertTrue(b'Detected type change from VARCHAR(length=128) ' b'to String(length=10)' in e) flask-migrate-4.0.7/tests/test_multidb_migrate.py000066400000000000000000000057131457365025700222170ustar00rootroot00000000000000import os import shutil import unittest import subprocess import shlex import sqlite3 def run_cmd(app, cmd): """Run a command and return a tuple with (stdout, stderr, exit_code)""" os.environ['FLASK_APP'] = app process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = process.communicate() print('\n$ ' + cmd) print(stdout.decode('utf-8')) print(stderr.decode('utf-8')) return stdout, stderr, process.wait() class TestMigrate(unittest.TestCase): def setUp(self): os.chdir(os.path.split(os.path.abspath(__file__))[0]) try: os.remove('app1.db') os.remove('app2.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass def tearDown(self): try: os.remove('app1.db') os.remove('app2.db') except OSError: pass try: shutil.rmtree('migrations') except OSError: pass def test_multidb_migrate_upgrade(self): (o, e, s) = run_cmd('app_multidb.py', 'flask db init --multidb') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_multidb.py', 'flask db migrate') self.assertTrue(s == 0) (o, e, s) = run_cmd('app_multidb.py', 'flask db upgrade') self.assertTrue(s == 0) # ensure the tables are in the correct databases conn1 = sqlite3.connect('app1.db') c = conn1.cursor() c.execute('select name from sqlite_master') tables = c.fetchall() conn1.close() self.assertIn(('alembic_version',), tables) self.assertIn(('user',), tables) conn2 = sqlite3.connect('app2.db') c = conn2.cursor() c.execute('select name from sqlite_master') tables = c.fetchall() conn2.close() self.assertIn(('alembic_version',), tables) self.assertIn(('group',), tables) # ensure the databases can be written to from .app_multidb import app, db, User, Group with app.app_context(): db.engine.dispose() db.session.add(User(name='test')) db.session.add(Group(name='group')) db.session.commit() # ensure the downgrade works (o, e, s) = run_cmd('app_multidb.py', 'flask db downgrade') self.assertTrue(s == 0) conn1 = sqlite3.connect('app1.db') c = conn1.cursor() c.execute('select name from sqlite_master') tables = c.fetchall() conn1.close() self.assertIn(('alembic_version',), tables) self.assertNotIn(('user',), tables) conn2 = sqlite3.connect('app2.db') c = conn2.cursor() c.execute('select name from sqlite_master') tables = c.fetchall() conn2.close() self.assertIn(('alembic_version',), tables) self.assertNotIn(('group',), tables) flask-migrate-4.0.7/tox.ini000066400000000000000000000010351457365025700156000ustar00rootroot00000000000000[tox] envlist=flake8,py37,py38,py39,py310,py311,pypy3,docs skip_missing_interpreters=True [gh-actions] python = 3.7: py37 3.8: py38 3.9: py39 3.10: py310 3.11: py311 pypy-3: pypy3 [testenv] commands= pip install -e . pip install {env:SQLALCHEMY_VERSION:sqlalchemy>=2} pytest -p no:logging deps= pytest [testenv:flake8] deps= flake8 commands= flake8 --exclude=".*" src/flask_migrate tests [testenv:docs] changedir=docs deps= sphinx allowlist_externals= make commands= make html