root/galaxy-central/eggs/sqlalchemy_migrate-0.5.4-py2.6.egg/migrate/versioning/api.py @ 3

リビジョン 3, 11.5 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1"""
2   This module provides an external API to the versioning system.
3
4   .. versionchanged:: 0.4.5
5    ``--preview_sql`` displays source file when using SQL scripts. If Python script is used,
6    it runs the action with mocked engine and returns captured SQL statements.
7
8   .. versionchanged:: 0.4.5
9    Deprecated ``--echo`` parameter in favour of new :func:`migrate.versioning.util.construct_engine` behavior.
10"""
11
12# Dear migrate developers,
13#
14# please do not comment this module using sphinx syntax because its
15# docstrings are presented as user help and most users cannot
16# interpret sphinx annotated ReStructuredText.
17#
18# Thanks,
19# Jan Dittberner
20
21import sys
22import inspect
23import warnings
24
25from migrate.versioning import (exceptions, repository, schema, version,
26    script as script_) # command name conflict
27from migrate.versioning.util import catch_known_errors, construct_engine
28
29
30__all__ = [
31    'help',
32    'create',
33    'script',
34    'script_sql',
35    'make_update_script_for_model',
36    'version',
37    'source',
38    'version_control',
39    'db_version',
40    'upgrade',
41    'downgrade',
42    'drop_version_control',
43    'manage',
44    'test',
45    'compare_model_to_db',
46    'create_model',
47    'update_db_from_model',
48]
49
50Repository = repository.Repository
51ControlledSchema = schema.ControlledSchema
52VerNum = version.VerNum
53PythonScript = script_.PythonScript
54SqlScript = script_.SqlScript
55
56
57# deprecated
58def help(cmd=None, **opts):
59    """%prog help COMMAND
60
61    Displays help on a given command.
62    """
63    if cmd is None:
64        raise exceptions.UsageError(None)
65    try:
66        func = globals()[cmd]
67    except:
68        raise exceptions.UsageError(
69            "'%s' isn't a valid command. Try 'help COMMAND'" % cmd)
70    ret = func.__doc__
71    if sys.argv[0]:
72        ret = ret.replace('%prog', sys.argv[0])
73    return ret
74
75@catch_known_errors
76def create(repository, name, **opts):
77    """%prog create REPOSITORY_PATH NAME [--table=TABLE]
78
79    Create an empty repository at the specified path.
80
81    You can specify the version_table to be used; by default, it is
82    'migrate_version'.  This table is created in all version-controlled
83    databases.
84    """
85    repo_path = Repository.create(repository, name, **opts)
86
87
88@catch_known_errors
89def script(description, repository, **opts):
90    """%prog script [--repository=REPOSITORY_PATH] DESCRIPTION
91
92    Create an empty change script using the next unused version number
93    appended with the given description.
94
95    For instance, manage.py script "Add initial tables" creates:
96    repository/versions/001_Add_initial_tables.py
97    """
98    repo = Repository(repository)
99    repo.create_script(description, **opts)
100
101
102@catch_known_errors
103def script_sql(database, repository, **opts):
104    """%prog script_sql [--repository=REPOSITORY_PATH] DATABASE
105
106    Create empty change SQL scripts for given DATABASE, where DATABASE
107    is either specific ('postgres', 'mysql', 'oracle', 'sqlite', etc.)
108    or generic ('default').
109
110    For instance, manage.py script_sql postgres creates:
111    repository/versions/001_postgres_upgrade.sql and
112    repository/versions/001_postgres_postgres.sql
113    """
114    repo = Repository(repository)
115    repo.create_script_sql(database, **opts)
116
117
118def test(repository, url=None, **opts):
119    """%prog test REPOSITORY_PATH URL [VERSION]
120
121    Performs the upgrade and downgrade option on the given
122    database. This is not a real test and may leave the database in a
123    bad state. You should therefore better run the test on a copy of
124    your database.
125    """
126    engine = construct_engine(url, **opts)
127    repos = Repository(repository)
128    script = repos.version(None).script()
129
130    # Upgrade
131    print "Upgrading...",
132    script.run(engine, 1)
133    print "done"
134
135    print "Downgrading...",
136    script.run(engine, -1)
137    print "done"
138    print "Success"
139
140
141def version(repository, **opts):
142    """%prog version REPOSITORY_PATH
143
144    Display the latest version available in a repository.
145    """
146    repo = Repository(repository)
147    return repo.latest
148
149
150def source(version, dest=None, repository=None, **opts):
151    """%prog source VERSION [DESTINATION] --repository=REPOSITORY_PATH
152
153    Display the Python code for a particular version in this
154    repository.  Save it to the file at DESTINATION or, if omitted,
155    send to stdout.
156    """
157    if repository is None:
158        raise exceptions.UsageError("A repository must be specified")
159    repo = Repository(repository)
160    ret = repo.version(version).script().source()
161    if dest is not None:
162        dest = open(dest, 'w')
163        dest.write(ret)
164        dest.close()
165        ret = None
166    return ret
167
168
169def version_control(url, repository, version=None, **opts):
170    """%prog version_control URL REPOSITORY_PATH [VERSION]
171
172    Mark a database as under this repository's version control.
173
174    Once a database is under version control, schema changes should
175    only be done via change scripts in this repository.
176
177    This creates the table version_table in the database.
178
179    The url should be any valid SQLAlchemy connection string.
180
181    By default, the database begins at version 0 and is assumed to be
182    empty.  If the database is not empty, you may specify a version at
183    which to begin instead. No attempt is made to verify this
184    version's correctness - the database schema is expected to be
185    identical to what it would be if the database were created from
186    scratch.
187    """
188    engine = construct_engine(url, **opts)
189    ControlledSchema.create(engine, repository, version)
190
191
192def db_version(url, repository, **opts):
193    """%prog db_version URL REPOSITORY_PATH
194
195    Show the current version of the repository with the given
196    connection string, under version control of the specified
197    repository.
198
199    The url should be any valid SQLAlchemy connection string.
200    """
201    engine = construct_engine(url, **opts)
202    schema = ControlledSchema(engine, repository)
203    return schema.version
204
205
206def upgrade(url, repository, version=None, **opts):
207    """%prog upgrade URL REPOSITORY_PATH [VERSION] [--preview_py|--preview_sql]
208
209    Upgrade a database to a later version.
210
211    This runs the upgrade() function defined in your change scripts.
212
213    By default, the database is updated to the latest available
214    version. You may specify a version instead, if you wish.
215
216    You may preview the Python or SQL code to be executed, rather than
217    actually executing it, using the appropriate 'preview' option.
218    """
219    err = "Cannot upgrade a database of version %s to version %s. "\
220        "Try 'downgrade' instead."
221    return _migrate(url, repository, version, upgrade=True, err=err, **opts)
222
223
224def downgrade(url, repository, version, **opts):
225    """%prog downgrade URL REPOSITORY_PATH VERSION [--preview_py|--preview_sql]
226
227    Downgrade a database to an earlier version.
228
229    This is the reverse of upgrade; this runs the downgrade() function
230    defined in your change scripts.
231
232    You may preview the Python or SQL code to be executed, rather than
233    actually executing it, using the appropriate 'preview' option.
234    """
235    err = "Cannot downgrade a database of version %s to version %s. "\
236        "Try 'upgrade' instead."
237    return _migrate(url, repository, version, upgrade=False, err=err, **opts)
238   
239
240def drop_version_control(url, repository, **opts):
241    """%prog drop_version_control URL REPOSITORY_PATH
242
243    Removes version control from a database.
244    """
245    engine = construct_engine(url, **opts)
246    schema = ControlledSchema(engine, repository)
247    schema.drop()
248
249
250def manage(file, **opts):
251    """%prog manage FILENAME VARIABLES...
252
253    Creates a script that runs Migrate with a set of default values.
254
255    For example::
256
257        %prog manage manage.py --repository=/path/to/repository \
258--url=sqlite:///project.db
259
260    would create the script manage.py. The following two commands
261    would then have exactly the same results::
262
263        python manage.py version
264        %prog version --repository=/path/to/repository
265    """
266    return repository.manage(file, **opts)
267
268
269def compare_model_to_db(url, model, repository, **opts):
270    """%prog compare_model_to_db URL MODEL REPOSITORY_PATH
271
272    Compare the current model (assumed to be a module level variable
273    of type sqlalchemy.MetaData) against the current database.
274
275    NOTE: This is EXPERIMENTAL.
276    """  # TODO: get rid of EXPERIMENTAL label
277    engine = construct_engine(url, **opts)
278    print ControlledSchema.compare_model_to_db(engine, model, repository)
279
280
281def create_model(url, repository, **opts):
282    """%prog create_model URL REPOSITORY_PATH
283
284    Dump the current database as a Python model to stdout.
285
286    NOTE: This is EXPERIMENTAL.
287    """  # TODO: get rid of EXPERIMENTAL label
288    engine = construct_engine(url, **opts)
289    declarative = opts.get('declarative', False)
290    print ControlledSchema.create_model(engine, repository, declarative)
291
292
293# TODO: get rid of this? if we don't add back path param
294@catch_known_errors
295def make_update_script_for_model(url, oldmodel, model, repository, **opts):
296    """%prog make_update_script_for_model URL OLDMODEL MODEL REPOSITORY_PATH
297
298    Create a script changing the old Python model to the new (current)
299    Python model, sending to stdout.
300
301    NOTE: This is EXPERIMENTAL.
302    """  # TODO: get rid of EXPERIMENTAL label
303    engine = construct_engine(url, **opts)
304    print PythonScript.make_update_script_for_model(
305        engine, oldmodel, model, repository, **opts)
306
307
308def update_db_from_model(url, model, repository, **opts):
309    """%prog update_db_from_model URL MODEL REPOSITORY_PATH
310
311    Modify the database to match the structure of the current Python
312    model. This also sets the db_version number to the latest in the
313    repository.
314
315    NOTE: This is EXPERIMENTAL.
316    """  # TODO: get rid of EXPERIMENTAL label
317    engine = construct_engine(url, **opts)
318    schema = ControlledSchema(engine, repository)
319    schema.update_db_from_model(model)
320
321
322def _migrate(url, repository, version, upgrade, err, **opts):
323    engine = construct_engine(url, **opts)
324    schema = ControlledSchema(engine, repository)
325    version = _migrate_version(schema, version, upgrade, err)
326
327    changeset = schema.changeset(version)
328    for ver, change in changeset:
329        nextver = ver + changeset.step
330        print '%s -> %s... ' % (ver, nextver)
331
332        if opts.get('preview_sql'):
333            if isinstance(change, PythonScript):
334                print change.preview_sql(url, changeset.step, **opts)
335            elif isinstance(change, SqlScript):
336                print change.source()
337
338        elif opts.get('preview_py'):
339            source_ver = max(ver, nextver)
340            module = schema.repository.version(source_ver).script().module
341            funcname = upgrade and "upgrade" or "downgrade"
342            func = getattr(module, funcname)
343            if isinstance(change, PythonScript):
344                print inspect.getsource(func)
345            else:
346                raise UsageError("Python source can be only displayed"
347                    " for python migration files")
348        else:
349            schema.runchange(ver, change, changeset.step)
350            print 'done'
351
352
353def _migrate_version(schema, version, upgrade, err):
354    if version is None:
355        return version
356    # Version is specified: ensure we're upgrading in the right direction
357    # (current version < target version for upgrading; reverse for down)
358    version = VerNum(version)
359    cur = schema.version
360    if upgrade is not None:
361        if upgrade:
362            direction = cur <= version
363        else:
364            direction = cur >= version
365        if not direction:
366            raise exceptions.KnownError(err % (cur, version))
367    return version
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。