1 """Quickstart command to generate a new project.
2
3 Quickstart takes the files from turbogears.quickstart and processes them to produce
4 a new, ready-to-run project.
5
6 """
7
8 import optparse
9 import os
10 import re
11 import shutil
12 import stat
13 import sys
14
15 import pkg_resources
16 import turbogears
17
18 from paste.script import templates, create_distro
19
20
21 beginning_letter = re.compile(r'^[^a-z]*')
22 valid_only = re.compile(r'[^a-z0-9_]')
23
24
26 - def run(self, command, output_dirs, vars):
27 vars.setdefault('einame', vars['project'].replace('-', '_'))
28 vars.setdefault('turbogearsversion',
29 pkg_resources.get_distribution('turbogears').version)
30 vars.setdefault('sys_executable', os.path.normpath(sys.executable))
31 super(TGTemplate, self).run(command, output_dirs, vars)
32
33
42
43
51
52
54 required_templates = ['turbogears']
55 _template_dir = pkg_resources.resource_filename(
56 'turbogears.qstemplates',
57 'quickstartbig')
58 summary = "For more complex projects"
59 use_cheetah = True
60
61 - def post(self, command, output_dir, vars):
62 packagedir = os.path.join(output_dir, vars['package'])
63 controllersdir = os.path.join(packagedir, 'controllers')
64 controllersfile = os.path.join(packagedir, 'controllers.py')
65 rootfile = os.path.join(controllersdir, 'root.py')
66 if (os.path.exists(controllersdir)
67 and os.path.exists(controllersfile)):
68 controllerstext = open(controllersfile).read()
69 roottext = open(rootfile).read()
70 from paste.script.copydir import query_interactive
71 thesame = controllerstext == roottext
72 if not thesame:
73 print "\nYou seem to be upgrading from a smaller quickstart."
74 print "There is currently a controllers package and a"
75 print "controllers module, which would get confusing."
76 if not command.simulate and (controllerstext == roottext
77 or query_interactive(controllersfile, rootfile,
78 controllerstext, roottext, False)):
79 shutil.copyfile(controllersfile, rootfile)
80 try:
81 if not os.path.exists(os.path.join(os.path.dirname(
82 os.path.abspath(controllersfile)), '.svn')):
83 raise OSError
84 command.run_command('svn', 'revert', controllersfile)
85 command.run_command('svn', 'delete', controllersfile)
86 except OSError:
87 os.unlink(controllersfile)
88 controllerspyc = controllersfile + "c"
89 if os.path.exists(controllerspyc):
90 os.unlink(controllerspyc)
91
92
99
100
102 dist = pkg_resources.get_distribution('TurboGears')
103 for r in set(dist.requires((name,))) - set(dist.requires()):
104 if r.project_name.lower() == (pkg or name):
105 return r
106 raise ValueError("Did not find matching %s requirement"
107 " in the TurboGears setup.py:extras_require." % name)
108
109
111 "Implementation of quickstart."
112
113 desc = "Create a new TurboGears project"
114
115 name = None
116 package = None
117 templates = 'turbogears'
118 svn_repository = None
119 sqlalchemy = False
120 sqlobject = False
121 elixir = False
122 identity = False
123
124 prompt_identity = True
125
127 parser = optparse.OptionParser(
128 usage="%prog quickstart [options] [project name]",
129 version="%prog " + version)
130 parser.add_option("-s", "--sqlalchemy",
131 help="use SQLAlchemy instead of SQLObject (the default)",
132 action="store_true", dest="sqlalchemy", default=False)
133 parser.add_option("-e", "--elixir",
134 help="use SQLAlchemy Elixir instead of SQLObject",
135 action="store_true", dest="elixir", default=False)
136 parser.add_option("-o", "--sqlobject",
137 help="use SQLObject instead of SQLAlchemy",
138 action="store_true", dest="sqlobject", default=False)
139 parser.add_option("-i", "--identity",
140 help="provide Identity support",
141 action="store_true", dest="identity", default=False)
142 parser.add_option("", "--no-identity",
143 help="don't prompt for Identity support (ignored with -i)",
144 action="store_false", dest="prompt_identity", default=True)
145 parser.add_option("", "--table-prefix",
146 help="add the specified prefix to all generated tables",
147 dest="table_prefix")
148 parser.add_option("-p", "--package",
149 help="package name for the code",
150 dest="package")
151 parser.add_option("-t", "--templates",
152 help="user specific templates",
153 dest="templates", default=self.templates)
154 parser.add_option("-r", "--svn-repository", metavar="REPOS",
155 help="create project in given SVN repository",
156 dest="svn_repository", default=self.svn_repository)
157
158 parser.add_option("--dry-run",
159 help="dry run (don't actually do anything)",
160 action="store_true", dest="dry_run")
161
162 options, args = parser.parse_args()
163 self.__dict__.update(options.__dict__)
164
165 if not True in (self.elixir, self.sqlalchemy, self.sqlobject):
166 self.sqlalchemy = True
167
168 if self.elixir:
169 self.sqlalchemy = True
170 self.sqlobject = False
171 elif self.sqlalchemy:
172 self.sqlobject = False
173 if self.sqlobject:
174 self.sqlalchemy = False
175
176 if self.table_prefix:
177 self.table_prefix_always = self.table_prefix
178 else:
179 self.table_prefix_always = 'tg_'
180 self.table_prefix = ''
181
182 if args:
183 self.name = args[0]
184 self.turbogearsversion = version
185
187 "Quickstarts the new project."
188
189 while not self.name:
190 self.name = raw_input("Enter project name: ")
191
192 while not self.package:
193 package = self.name.lower()
194 package = beginning_letter.sub("", package)
195 package = valid_only.sub("", package)
196 self.package = raw_input("Enter package name [%s]: " % package)
197 if not self.package:
198 self.package = package
199
200 doidentity = self.identity
201 while self.prompt_identity and not doidentity:
202 doidentity = raw_input("Do you need Identity "
203 "(usernames/passwords) in this project? [no] ")
204
205 doidentity = doidentity.lower()
206
207 if not doidentity or doidentity.startswith('n'):
208 self.identity = "none"
209 break
210
211 if doidentity.startswith("y"):
212 doidentity = True
213 break
214
215 print "Please enter y(es) or n(o)."
216 doidentity = None
217
218 if doidentity is True:
219 if self.sqlalchemy or self.elixir:
220 self.identity = 'sqlalchemy'
221 else:
222 self.identity = 'sqlobject'
223 else:
224 self.identity = 'none'
225
226 self.name = pkg_resources.safe_name(self.name)
227
228 env = pkg_resources.Environment()
229 if self.name.lower() in env:
230 print 'The name "%s" is already in use by' % self.name,
231 for dist in env[self.name]:
232 print dist
233 return
234
235 import imp
236 try:
237 if imp.find_module(self.package):
238 print 'The package name "%s" is already in use' % self.package
239 return
240 except ImportError:
241 pass
242
243 if os.path.exists(self.name):
244 print 'A directory called "%s" already exists. Exiting.' % self.name
245 return
246
247 command = create_distro.CreateDistroCommand("quickstart")
248 cmd_args = []
249 for template in self.templates.split():
250 cmd_args.append("--template=%s" % template)
251 if self.svn_repository:
252 cmd_args.append("--svn-repository=%s" % self.svn_repository)
253 if self.dry_run:
254 cmd_args.append("--simulate")
255 cmd_args.append("-q")
256 cmd_args.append(self.name)
257 cmd_args.append("sqlalchemy=%s" % self.sqlalchemy)
258 cmd_args.append("elixir=%s" % self.elixir)
259 cmd_args.append("sqlobject=%s" % self.sqlobject)
260 cmd_args.append("identity=%s" % self.identity)
261 cmd_args.append("table_prefix=%s" % self.table_prefix)
262 cmd_args.append("table_prefix_always=%s" % self.table_prefix_always)
263 cmd_args.append("package=%s" % self.package)
264
265
266
267 if self.sqlobject:
268 sqlobjectversion = str(get_requirement('sqlobject'))
269 cmd_args.append("sqlobjectversion=%s" % sqlobjectversion)
270 if self.sqlalchemy:
271 sqlalchemyversion = str(get_requirement('sqlalchemy'))
272 cmd_args.append("sqlalchemyversion=%s" % sqlalchemyversion)
273 if self.elixir:
274 elixirversion = str(get_requirement('sqlalchemy', 'elixir'))
275 cmd_args.append("elixirversion=%s" % elixirversion)
276
277 command.run(cmd_args)
278
279 if not self.dry_run:
280 os.chdir(self.name)
281 if self.sqlobject:
282
283
284
285 sodir = '%s/sqlobject-history' % self.package
286 if not os.path.exists(sodir):
287 os.mkdir(sodir)
288 try:
289 if not os.path.exists(os.path.join(os.path.dirname(
290 os.path.abspath(sodir)), '.svn')):
291 raise OSError
292 command.run_command('svn', 'add', sodir)
293 except OSError:
294 pass
295
296 startscript = 'start-%s.py' % self.package
297 if os.path.exists(startscript):
298 oldmode = os.stat(startscript).st_mode
299 os.chmod(startscript,
300 oldmode | stat.S_IXUSR)
301 sys.argv = ['setup.py', 'egg_info']
302 imp.load_module('setup', *imp.find_module('setup', ['.']))
303
304
305 for base, path, files in os.walk('./'):
306 for file in files:
307 if file == 'empty':
308 os.remove(os.path.join(base, file))
309
310
312 "Implementation of update"
313
314 desc = "Update an existing TurboGears project"
315 need_project = True
316
317 name = None
318 templates = 'turbogears'
319 identity = False
320 sqlalchemy = True
321 sqlobject = False
322 elixir = True
323
325 self.parser = parser = optparse.OptionParser(usage="%prog update [options]",
326 version="%prog " + version)
327 parser.add_option("-s", "--sqlalchemy",
328 help="use SQLAlchemy instead of SQLObject",
329 action="store_true", dest="sqlalchemy", default=False)
330 parser.add_option("-e", "--elixir",
331 help="use SQLAlchemy Elixir instead of SQLObject",
332 action="store_true", dest="elixir", default=False)
333 parser.add_option("-o", "--sqlobject",
334 help="use SQLObject instead of SQLAlchemy",
335 action="store_true", dest="sqlobject", default=False)
336 parser.add_option("-i", "--identity",
337 help="provide Identity support",
338 action="store_true", dest="identity", default=False)
339 parser.add_option("-t", "--templates", help="user specific templates",
340 dest="templates", default=self.templates)
341
342 self.turbogearsversion = version
343
345 "Updates an existing project"
346 self.name = turbogears.util.get_project_name()
347 self.package = turbogears.util.get_package_name()
348 turbogears.command.base.load_project_config()
349
350 try:
351 project_dist = pkg_resources.get_distribution(self.name)
352 project_requires = [r.project_name.lower()
353 for r in project_dist.requires()]
354 self.parser.set_defaults(
355 sqlobject = 'sqlobject' in project_requires,
356 sqlalchemy = 'sqlalchemy' in project_requires,
357 elixir = 'elixir' in project_requires)
358 except pkg_resources.DistributionNotFound:
359 print "Could not determine requirements for your application."
360 print "Please run 'python setup.py develop' to make your " + \
361 "application known to setuptools."
362
363 options, args = self.parser.parse_args()
364 self.__dict__.update(options.__dict__)
365
366 if not True in (self.elixir, self.sqlalchemy, self.sqlobject):
367 if turbogears.config.get('sqlobject.dburi'):
368 self.sqlobject = True
369 else:
370 self.sqlalchemy = True
371
372 if self.elixir:
373 self.sqlalchemy = True
374 self.sqlobject = False
375 elif self.sqlalchemy:
376 self.sqlobject = False
377 if self.sqlobject:
378 self.sqlalchemy = False
379
380 if not self.identity:
381 if turbogears.config.get('identity.on'):
382 self.identity = True
383
384 if self.identity:
385 if self.sqlalchemy:
386 self.identity = 'sqlalchemy'
387 else:
388 self.identity = 'sqlobject'
389 else:
390 self.identity = 'none'
391
392 currentdir = os.path.basename(os.getcwd())
393 if not currentdir == self.name:
394 print ('It looks like your project directory "%s" is named '
395 'incorrectly.' % currentdir)
396 print 'Please rename it to "%s".' % self.name
397 return
398
399 command = create_distro.CreateDistroCommand("update")
400 cmd_args = []
401 cmd_args.append('-o../')
402 for template in self.templates.split():
403 cmd_args.append("--template=%s" % template)
404 cmd_args.append(self.name)
405 cmd_args.append('sqlalchemy=%s' % self.sqlalchemy)
406 cmd_args.append('elixir=%s' % self.elixir)
407 cmd_args.append('sqlobject=%s' % self.sqlobject)
408 cmd_args.append('identity=%s' % self.identity)
409 cmd_args.append('package=%s' % self.package)
410
411
412
413
414 if self.sqlobject:
415 sqlobjectversion = str(get_requirement('sqlobject'))
416 cmd_args.append('sqlobjectversion=%s' % sqlobjectversion)
417
418 if self.sqlalchemy:
419 sqlalchemyversion = str(get_requirement('sqlalchemy'))
420 cmd_args.append('sqlalchemyversion=%s' % sqlalchemyversion)
421
422 if self.elixir:
423 elixirversion = str(get_requirement('sqlalchemy', 'elixir'))
424 cmd_args.append('elixirversion=%s' % elixirversion)
425
426 command.run(cmd_args)
427
428 startscript = 'start-%s.py' % self.package
429 if os.path.exists(startscript):
430 oldmode = os.stat(startscript).st_mode
431 os.chmod(startscript,
432 oldmode | stat.S_IXUSR)
433 sys.argv = ['setup.py', 'egg_info']
434 import imp
435 imp.load_module('setup', *imp.find_module('setup', ['.']))
436
437
438 for base, path, files in os.walk('./'):
439 for file in files:
440 if file == 'empty':
441 os.remove(os.path.join(base, file))
442