we are using Tempita for templates; adding most basic pylons template

This commit is contained in:
iElectric 2009-08-07 12:58:04 +02:00
parent 78ce747e25
commit 3d3f4e0391
15 changed files with 108 additions and 29 deletions

View File

@ -1,7 +1,7 @@
0.5.5 0.5.5
----- -----
- added option to define custom templates through option ``--templates_path``, read more in :ref:`tutorial section <custom-templates>` - added option to define custom templates through option ``--templates_path`` and ``--templates_theme``, read more in :ref:`tutorial section <custom-templates>`
- url parameter can also be an Engine instance (this usage is discouraged though sometimes necessary) - url parameter can also be an Engine instance (this usage is discouraged though sometimes necessary)
- added support for SQLAlchemy 0.6 (missing oracle and firebird) by Michael Bayer - added support for SQLAlchemy 0.6 (missing oracle and firebird) by Michael Bayer
- alter, create, drop column / rename table / rename index constructs now accept `alter_metadata` parameter. If True, it will modify Column/Table objects according to changes. Otherwise, everything will be untouched. - alter, create, drop column / rename table / rename index constructs now accept `alter_metadata` parameter. If True, it will modify Column/Table objects according to changes. Otherwise, everything will be untouched.

View File

@ -6,6 +6,8 @@ import shutil
import string import string
from pkg_resources import resource_filename from pkg_resources import resource_filename
from tempita import Template as TempitaTemplate
from migrate.versioning import exceptions, script, version, pathed, cfgparse from migrate.versioning import exceptions, script, version, pathed, cfgparse
from migrate.versioning.template import Template from migrate.versioning.template import Template
from migrate.versioning.base import * from migrate.versioning.base import *
@ -83,7 +85,7 @@ class Repository(pathed.Pathed):
:raises: :exc:`InvalidRepositoryError <migrate.versioning.exceptions.InvalidRepositoryError>` :raises: :exc:`InvalidRepositoryError <migrate.versioning.exceptions.InvalidRepositoryError>`
""" """
# Ensure the existance of required files # Ensure the existence of required files
try: try:
cls.require_found(path) cls.require_found(path)
cls.require_found(os.path.join(path, cls._config)) cls.require_found(os.path.join(path, cls._config))
@ -92,7 +94,7 @@ class Repository(pathed.Pathed):
raise exceptions.InvalidRepositoryError(path) raise exceptions.InvalidRepositoryError(path)
@classmethod @classmethod
def prepare_config(cls, tmpl_dir, config_file, name, **opts): def prepare_config(cls, tmpl_dir, name, options=None):
""" """
Prepare a project configuration file for a new project. Prepare a project configuration file for a new project.
@ -104,37 +106,43 @@ class Repository(pathed.Pathed):
:type name: string :type name: string
:returns: Populated config file :returns: Populated config file
""" """
# Prepare opts if options is None:
defaults = dict( options = {}
version_table = 'migrate_version', options.setdefault('version_table', 'migrate_version')
repository_id = name, options.setdefault('repository_id', name)
required_dbs = []) options.setdefault('required_dbs', [])
defaults.update(opts) tmpl = open(os.path.join(tmpl_dir, cls._config)).read()
ret = TempitaTemplate(tmpl).substitute(options)
# cleanup
del options['__template_name__']
tmpl = open(os.path.join(tmpl_dir, config_file)).read()
ret = string.Template(tmpl).substitute(defaults)
return ret return ret
@classmethod @classmethod
def create(cls, path, name, **opts): def create(cls, path, name, **opts):
"""Create a repository at a specified path""" """Create a repository at a specified path"""
cls.require_notfound(path) cls.require_notfound(path)
theme = opts.get('templates_theme', None) theme = opts.pop('templates_theme', None)
t_path = opts.pop('templates_path', None)
# Create repository # Create repository
tmpl_dir = Template(opts.pop('templates_path', None)).get_repository(theme=theme) tmpl_dir = Template(t_path).get_repository(theme=theme)
config_text = cls.prepare_config(tmpl_dir, cls._config, name, **opts)
shutil.copytree(tmpl_dir, path) shutil.copytree(tmpl_dir, path)
# Edit config defaults # Edit config defaults
config_text = cls.prepare_config(tmpl_dir, name, options=opts)
fd = open(os.path.join(path, cls._config), 'w') fd = open(os.path.join(path, cls._config), 'w')
fd.write(config_text) fd.write(config_text)
fd.close() fd.close()
opts['repository_name'] = name
# Create a management script # Create a management script
manager = os.path.join(path, 'manage.py') manager = os.path.join(path, 'manage.py')
Repository.create_manage_file(manager, theme=theme, repository=path) Repository.create_manage_file(manager, templates_theme=theme,
templates_path=t_path, **opts)
return cls(path) return cls(path)
@ -208,12 +216,12 @@ class Repository(pathed.Pathed):
"""Create a project management script (manage.py) """Create a project management script (manage.py)
:param file_: Destination file to be written :param file_: Destination file to be written
:param opts: Options that are passed to template :param opts: Options that are passed to :func:`migrate.versioning.shell.main`
""" """
mng_file = Template(opts.pop('templates_path', None)).get_manage(theme=opts.pop('templates_theme', None)) mng_file = Template(opts.pop('templates_path', None))\
vars_ = ",".join(["%s='%s'" % var for var in opts.iteritems()]) .get_manage(theme=opts.pop('templates_theme', None))
tmpl = open(mng_file).read() tmpl = open(mng_file).read()
fd = open(file_, 'w') fd = open(file_, 'w')
fd.write(tmpl % dict(defaults=vars_)) fd.write(TempitaTemplate(tmpl).substitute(opts))
fd.close() fd.close()

View File

@ -1,4 +0,0 @@
#!/usr/bin/env python
from migrate.versioning.shell import main
main(%(defaults)s)

View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
from migrate.versioning.shell import main
{{py:
_vars = locals().copy()
del _vars['__template_name__']
_vars.pop('repository_name')
defaults = ", ".join(["%s='%s'" % var for var in _vars.iteritems()])
}}
main({{ defaults }})

View File

@ -0,0 +1,29 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from sqlalchemy import engine_from_config
from paste.deploy.loadwsgi import ConfigLoader
from migrate.versioning.shell import main
from {{ locals().pop('repository_name') }}.model import migrations
if '-c' in sys.argv:
pos = sys.argv.index('-c')
conf_path = sys.argv[pos + 1]
del sys.argv[pos:pos + 2]
else:
conf_path = 'development.ini'
{{py:
_vars = locals().copy()
del _vars['__template_name__']
defaults = ", ".join(["%s='%s'" % var for var in _vars.iteritems()])
}}
conf_dict = ConfigLoader(conf_path).parser._sections['app:main']
# migrate supports passing url as an existing Engine instance (since 0.6.0)
# usage: migrate -c path/to/config.ini COMMANDS
main(url=engine_from_config(conf_dict), repository=migrations.__path__[0],{{ defaults }})

View File

@ -1,13 +1,13 @@
[db_settings] [db_settings]
# Used to identify which repository this database is versioned under. # Used to identify which repository this database is versioned under.
# You can use the name of your project. # You can use the name of your project.
repository_id=${repository_id} repository_id={{ locals().pop('repository_id') }}
# The name of the database table used to track the schema version. # The name of the database table used to track the schema version.
# This name shouldn't already be used by your project. # This name shouldn't already be used by your project.
# If this is changed once a database is under version control, you'll need to # If this is changed once a database is under version control, you'll need to
# change the table name in each database too. # change the table name in each database too.
version_table=${version_table} version_table={{ locals().pop('version_table') }}
# When committing a change script, Migrate will attempt to generate the # When committing a change script, Migrate will attempt to generate the
# sql for all supported databases; normally, if one of them fails - probably # sql for all supported databases; normally, if one of them fails - probably
@ -17,4 +17,4 @@ version_table=${version_table}
# entire commit will fail. List the databases your application will actually # entire commit will fail. List the databases your application will actually
# be using to ensure your updates to that database work properly. # be using to ensure your updates to that database work properly.
# This must be a list; example: ['postgres','sqlite'] # This must be a list; example: ['postgres','sqlite']
required_dbs=${required_dbs} required_dbs={{ locals().pop('required_dbs') }}

View File

@ -0,0 +1,4 @@
This is a database migration repository.
More information at
http://code.google.com/p/sqlalchemy-migrate/

View File

@ -0,0 +1,20 @@
[db_settings]
# Used to identify which repository this database is versioned under.
# You can use the name of your project.
repository_id={{ locals().pop('repository_id') }}
# The name of the database table used to track the schema version.
# This name shouldn't already be used by your project.
# If this is changed once a database is under version control, you'll need to
# change the table name in each database too.
version_table={{ locals().pop('version_table') }}
# When committing a change script, Migrate will attempt to generate the
# sql for all supported databases; normally, if one of them fails - probably
# because you don't have that database installed - it is ignored and the
# commit continues, perhaps ending successfully.
# Databases in this list MUST compile successfully during a commit, or the
# entire commit will fail. List the databases your application will actually
# be using to ensure your updates to that database work properly.
# This must be a list; example: ['postgres','sqlite']
required_dbs={{ locals().pop('required_dbs') }}

View File

@ -0,0 +1,11 @@
from sqlalchemy import *
from migrate import *
def upgrade(migrate_engine):
# Upgrade operations go here. Don't create your own engine; bind migrate_engine
# to your metadata
pass
def downgrade(migrate_engine):
# Operations to reverse the above upgrade go here.
pass

View File

@ -15,7 +15,7 @@ except ImportError:
pass pass
test_requirements = ['nose >= 0.10'] test_requirements = ['nose >= 0.10']
required_deps = ['sqlalchemy >= 0.5', 'decorator'] required_deps = ['sqlalchemy >= 0.5', 'decorator', 'tempita']
readme_file = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'README')) readme_file = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'README'))
setup( setup(

View File

@ -21,7 +21,7 @@ class TestConfigParser(fixture.Base):
def test_table_config(self): def test_table_config(self):
"""We should be able to specify the table to be used with a repository""" """We should be able to specify the table to be used with a repository"""
default_text = Repository.prepare_config(Template().get_repository(), default_text = Repository.prepare_config(Template().get_repository(),
Repository._config, 'repository_name') 'repository_name', {})
specified_text = Repository.prepare_config(Template().get_repository(), specified_text = Repository.prepare_config(Template().get_repository(),
Repository._config, 'repository_name', version_table='_other_table') 'repository_name', {'version_table': '_other_table'})
self.assertNotEquals(default_text, specified_text) self.assertNotEquals(default_text, specified_text)

View File

@ -59,5 +59,6 @@ class TestTemplate(fixture.Pathed):
# assert changes # assert changes
self.assertEqual(open(new_manage_dest).read(), MANAGE_CONTENTS) self.assertEqual(open(new_manage_dest).read(), MANAGE_CONTENTS)
self.assertEqual(open(os.path.join(new_repo_dest, 'manage.py')).read(), MANAGE_CONTENTS)
self.assertEqual(open(os.path.join(new_repo_dest, 'README')).read(), README_CONTENTS) self.assertEqual(open(os.path.join(new_repo_dest, 'README')).read(), README_CONTENTS)
self.assertEqual(open(os.path.join(new_repo_dest, 'versions/001_test.py')).read(), SCRIPT_FILE_CONTENTS) self.assertEqual(open(os.path.join(new_repo_dest, 'versions/001_test.py')).read(), SCRIPT_FILE_CONTENTS)