Package turbogears :: Package command :: Module quickstart

Source Code for Module turbogears.command.quickstart

  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   
25 -class TGTemplate(templates.Template):
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
34 -class BaseTemplate(TGTemplate):
35 egg_plugins = ['TurboGears'] 36 _template_dir = pkg_resources.resource_filename( 37 'turbogears.qstemplates', 38 'qsbase' 39 ) 40 summary = "tg base template" 41 use_cheetah = True
42 43
44 -class TurbogearsTemplate(TGTemplate):
45 required_templates = ['tgbase'] 46 _template_dir = pkg_resources.resource_filename( 47 'turbogears.qstemplates', 48 'quickstart') 49 summary = "web framework" 50 use_cheetah = True
51 52
53 -class TGBig(TGTemplate):
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
93 -class TGWidgetTemplate(TGTemplate):
94 required_templates = ['tgbase'] 95 _template_dir = pkg_resources.resource_filename( 96 'turbogears.qstemplates', 97 'widget') 98 summary = "TurboGears widget projects"
99 100
101 -def get_requirement(name, pkg=None):
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
110 -class quickstart:
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 # we ask user for identity usage in the default settings 124 prompt_identity = True 125
126 - def __init__(self, version):
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
186 - def run(self):
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 # set the exact ORM-version for the proper requirements 265 # it's extracted from our own requirements, so looking 266 # them up must be in sync (there must be the extras_require named sqlobject/sqlalchemy) 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 # Create the SQLObject history directory only when needed. 283 # With paste.script it's only possible to skip files, but 284 # not directories. So we are handling this manually. 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 # dirty hack to allow "empty" dirs 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
311 -class update:
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
324 - def __init__(self, version):
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
344 - def run(self):
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 # set the exact ORM-version for the proper requirements 411 # it's extracted from our own requirements, so looking 412 # them up must be in sync (there must be the extras_require 413 # named 'sqlobject'/'sqlalchemy') 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 # dirty hack to allow "empty" dirs 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