1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 from optparse import OptionParser
29 from code import InteractiveConsole
30 import sys
31
32
33
34
35
36
37 usage = "usage: %prog [options] command"
38
39 description = """
40 camelot_manage is oriented towards administrators of an installed
41 camelot application. It is used for interacting the database, the model
42 and migration of the database to a certain schema revision.
43
44 To use this application, PYTHONPATH should contain a valid settings.py file that
45 will be used to resolve the database engine and the model.
46 """
47
48 command_description = [
49 ('console', """Launches a python console with the model all setup for command line
50 interaction.
51
52 Within the example movie project one could do
53 the following to print a list of all movie titles to the screen::
54
55 from model import Movie
56 for movie in Movie.query.all():
57 print movie.title
58 """),
59 ('db_version', """Get the version of the database schema from the current database"""),
60
61 ('version', """Get the latest available database schema version"""),
62
63 ('upgrade', """Upgrade or downgrade the database to the specified version, use upgrade version_number."""),
64
65 ('version_control', """Put the database under version control"""),
66
67 ('schema_display', """Generate a graph of the database schema. The result is stored in schema.png. This
68 option requires pydot to be installed."""),
69 ]
70
71
72
73
74
75 __doc__ = description
76
77 for command, desc in command_description:
78 __doc__ += "\n.. cmdoption:: %s\n\n"%command
79 for line in desc.split('\n'):
80 __doc__ += " %s\n"%line
81
82 __doc__ += """
83 .. image:: ../_static/schema.png
84 :width: 400"""
85
86
87
88
103
105 "Cache the stdout text so we can analyze it before returning it"
107 - def reset(self): self.out = []
110 output = '\n'.join(self.out)
111 self.reset()
112 return output
113
114 -class Shell(InteractiveConsole):
115 "Wrapper around Python that can filter input/output to the shell"
117 self.stdout = sys.stdout
118 self.cache = FileCacher()
119 InteractiveConsole.__init__(self, locals)
120 return
123 - def push(self,line):
135
137 from camelot.core.schema_display import create_uml_graph
138 from sqlalchemy import orm
139 from elixir import entities
140 mappers = [orm.class_mapper(e) for e in entities]
141 graph = create_uml_graph(mappers,
142 show_operations=False,
143 show_multiplicity_one=False
144 )
145 graph.write_png(image_path)
146
150
152 import camelot
153 parser = CommandOptionParser(usage=usage,
154 description=description,
155 version=camelot.__version__)
156 (_options, args) = parser.parse_args()
157 if not args:
158 parser.print_help()
159 elif args[0]=='console':
160 setup_model()
161 sh = Shell()
162 sh.interact()
163 elif args[0]=='schema_display':
164 setup_model()
165 schema_display()
166 elif args[0] in ('version_control', 'db_version', 'version', 'upgrade'):
167 import settings
168 from migrate.versioning.repository import Repository
169 from migrate.versioning.schema import ControlledSchema
170 from sqlalchemy.exceptions import NoSuchTableError
171 migrate_engine = settings.ENGINE()
172 repository = Repository(settings.REPOSITORY)
173 schema = None
174 if args[0]=='version_control':
175 migrate_connection = migrate_engine.connect()
176 transaction = migrate_connection.begin()
177 try:
178 schema = ControlledSchema.create(migrate_engine, repository)
179 transaction.commit()
180 except:
181 transaction.rollback()
182 raise
183 finally:
184 migrate_connection.close()
185 print 'database was put under version control'
186 try:
187 schema = ControlledSchema(migrate_engine, repository)
188 except NoSuchTableError:
189 print 'database not yet under version control, use the version_control command first.'
190 if schema:
191 if args[0]=='db_version':
192 print schema.version
193 elif args[0]=='version':
194 print repository.latest
195 elif args[0]=='upgrade':
196 migrate_connection = migrate_engine.connect()
197 if len(args)>=2:
198 version = int(args[1])
199 else:
200 version = repository.latest
201
202
203
204
205 try:
206 if schema.version == version:
207 print 'database is allready at requested version'
208 if schema.version <= version:
209 step = 1
210 else:
211 step = -1
212 for i in range(schema.version+step, version+step, step):
213 transaction = migrate_connection.begin()
214 try:
215 schema.upgrade(i)
216 transaction.commit()
217 if step==1:
218 print 'upgrade %s'%i
219 else:
220 print 'downgrade %s'%i
221 except:
222 transaction.rollback()
223 raise
224 finally:
225 migrate_connection.close()
226 else:
227 parser.print_help()
228
229 if __name__ == '__main__':
230 main()
231