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) and \ 67 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", 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( 143 "", "--no-identity", 144 help="Don't prompt for Identity support (ignored if -i is on)", 145 action="store_false", dest="prompt_identity", default=True) 146 parser.add_option("-p", "--package", 147 help="package name for the code", 148 dest="package") 149 parser.add_option("-t", "--templates", 150 help="user specific templates", 151 dest="templates", default=self.templates) 152 parser.add_option("-r", "--svn-repository", metavar="REPOS", 153 help="create project in given SVN repository", 154 dest="svn_repository", default=self.svn_repository) 155 parser.add_option("--dry-run", 156 help="dry run (don't actually do anything)", 157 action="store_true", dest="dry_run") 158 159 options, args = parser.parse_args() 160 self.__dict__.update(options.__dict__) 161 162 if not True in [self.elixir, self.sqlalchemy, self.sqlobject]: 163 self.sqlalchemy = True 164 165 if self.elixir: 166 self.sqlalchemy = True 167 self.sqlobject = False 168 elif self.sqlalchemy: 169 self.sqlobject = False 170 if self.sqlobject: 171 self.sqlalchemy = False 172 173 if args: 174 self.name = args[0] 175 self.turbogearsversion = version
176
177 - def run(self):
178 "Quickstarts the new project." 179 180 while not self.name: 181 self.name = raw_input("Enter project name: ") 182 183 while not self.package: 184 package = self.name.lower() 185 package = beginning_letter.sub("", package) 186 package = valid_only.sub("", package) 187 self.package = raw_input("Enter package name [%s]: " % package) 188 if not self.package: 189 self.package = package 190 191 doidentity = self.identity 192 while self.prompt_identity and not doidentity: 193 doidentity = raw_input("Do you need Identity " 194 "(usernames/passwords) in this project? [no] ") 195 196 doidentity = doidentity.lower() 197 198 if not doidentity or doidentity.startswith('n'): 199 self.identity = "none" 200 break 201 202 if doidentity.startswith("y"): 203 doidentity = True 204 break 205 206 print "Please enter y(es) or n(o)." 207 doidentity = None 208 209 if doidentity is True: 210 if self.sqlalchemy or self.elixir: 211 self.identity = "sqlalchemy" 212 else: 213 self.identity = "sqlobject" 214 else: 215 self.identity = "none" 216 217 self.name = pkg_resources.safe_name(self.name) 218 219 env = pkg_resources.Environment() 220 if self.name.lower() in env: 221 print 'The name "%s" is already in use by' % self.name, 222 for dist in env[self.name]: 223 print dist 224 return 225 226 import imp 227 try: 228 if imp.find_module(self.package): 229 print 'The package name "%s" is already in use' % self.package 230 return 231 except ImportError: 232 pass 233 234 if os.path.exists(self.name): 235 print 'A directory called "%s" already exists. Exiting.' % self.name 236 return 237 238 command = create_distro.CreateDistroCommand("quickstart") 239 cmd_args = [] 240 for template in self.templates.split(" "): 241 cmd_args.append("--template=%s" % template) 242 if self.svn_repository: 243 cmd_args.append("--svn-repository=%s" % self.svn_repository) 244 if self.dry_run: 245 cmd_args.append("--simulate") 246 cmd_args.append("-q") 247 cmd_args.append(self.name) 248 cmd_args.append("sqlalchemy=%s" % self.sqlalchemy) 249 cmd_args.append("elixir=%s" % self.elixir) 250 cmd_args.append("sqlobject=%s" % self.sqlobject) 251 cmd_args.append("identity=%s" % self.identity) 252 cmd_args.append("package=%s" % self.package) 253 # set the exact ORM-version for the proper requirements 254 # it's extracted from our own requirements, so looking 255 # them up must be in sync (there must be the extras_require named sqlobject/sqlalchemy) 256 if self.sqlobject: 257 sqlobjectversion = str(get_requirement('sqlobject')) 258 cmd_args.append("sqlobjectversion=%s" % sqlobjectversion) 259 if self.sqlalchemy: 260 sqlalchemyversion = str(get_requirement('sqlalchemy')) 261 cmd_args.append("sqlalchemyversion=%s" % sqlalchemyversion) 262 if self.elixir: 263 elixirversion = str(get_requirement('sqlalchemy', 'elixir')) 264 cmd_args.append("elixirversion=%s" % elixirversion) 265 266 command.run(cmd_args) 267 268 if not self.dry_run: 269 os.chdir(self.name) 270 if self.sqlobject: 271 # Create the SQLObject history directory only when needed. 272 # With paste.script it's only possible to skip files, but 273 # not directories. So we are handling this manually. 274 sodir = '%s/sqlobject-history' % self.package 275 if not os.path.exists(sodir): 276 os.mkdir(sodir) 277 try: 278 if not os.path.exists(os.path.join(os.path.dirname( 279 os.path.abspath(sodir)), '.svn')): 280 raise OSError 281 command.run_command('svn', 'add', sodir) 282 except OSError: 283 pass 284 285 startscript = "start-%s.py" % self.package 286 if os.path.exists(startscript): 287 oldmode = os.stat(startscript).st_mode 288 os.chmod(startscript, 289 oldmode | stat.S_IXUSR) 290 sys.argv = ["setup.py", "egg_info"] 291 import imp 292 imp.load_module("setup", *imp.find_module("setup", ["."])) 293 294 # dirty hack to allow "empty" dirs 295 for base, path, files in os.walk("./"): 296 for file in files: 297 if file == "empty": 298 os.remove(os.path.join(base, file))
299 300
301 -class update:
302 "Implementation of update" 303 304 desc = "Update an existing turbogears project" 305 need_project = True 306 307 name = None 308 templates = "turbogears" 309 identity = False 310 sqlalchemy = True 311 sqlobject = False 312 elixir = True 313
314 - def __init__(self, version):
315 self.parser = parser = optparse.OptionParser(usage="%prog update [options]", 316 version="%prog " + version) 317 parser.add_option("-s", "--sqlalchemy", 318 help="use SQLAlchemy instead of SQLObject", 319 action="store_true", dest="sqlalchemy", default=False) 320 parser.add_option("-e", "--elixir", 321 help="use SQLAlchemy Elixir instead of SQLObject", 322 action="store_true", dest="elixir", default=False) 323 parser.add_option("-o", "--sqlobject", 324 help="use SQLObject instead of SQLAlchemy", 325 action="store_true", dest="sqlobject", default=False) 326 parser.add_option("-i", "--identity", 327 help="provide Identity support", 328 action="store_true", dest="identity", default=False) 329 parser.add_option("-t", "--templates", help="user specific templates", 330 dest="templates", default=self.templates) 331 332 self.turbogearsversion = version
333
334 - def run(self):
335 "Updates an existing project" 336 self.name = turbogears.util.get_project_name() 337 self.package = turbogears.util.get_package_name() 338 turbogears.command.base.load_project_config() 339 340 try: 341 project_dist = pkg_resources.get_distribution(self.name) 342 project_requires = [r.project_name.lower() 343 for r in project_dist.requires()] 344 self.parser.set_defaults( 345 sqlobject = 'sqlobject' in project_requires, 346 sqlalchemy = 'sqlalchemy' in project_requires, 347 elixir = 'elixir' in project_requires) 348 except pkg_resources.DistributionNotFound: 349 print "Could not determine requirements for your application." 350 print "Please run 'python setup.py develop' to make your " + \ 351 "application known to setuptools." 352 353 options, args = self.parser.parse_args() 354 self.__dict__.update(options.__dict__) 355 356 if not True in [self.elixir, self.sqlalchemy, self.sqlobject]: 357 if turbogears.config.get('sqlobject.dburi'): 358 self.sqlobject = True 359 else: 360 self.sqlalchemy = True 361 362 if self.elixir: 363 self.sqlalchemy = True 364 self.sqlobject = False 365 elif self.sqlalchemy: 366 self.sqlobject = False 367 if self.sqlobject: 368 self.sqlalchemy = False 369 370 if not self.identity: 371 if turbogears.config.get('identity.on'): 372 self.identity = True 373 374 if self.identity: 375 if self.sqlalchemy: 376 self.identity = 'sqlalchemy' 377 else: 378 self.identity = 'sqlobject' 379 else: 380 self.identity = 'none' 381 382 currentdir = os.path.basename(os.getcwd()) 383 if not currentdir == self.name: 384 print ('It looks like your project directory "%s" is named ' 385 'incorrectly.' % currentdir) 386 print 'Please rename it to "%s".' % self.name 387 return 388 389 command = create_distro.CreateDistroCommand("update") 390 cmd_args = [] 391 cmd_args.append("-o../") 392 for template in self.templates.split(" "): 393 cmd_args.append("--template=%s" % template) 394 cmd_args.append(self.name) 395 cmd_args.append("sqlalchemy=%s" % self.sqlalchemy) 396 cmd_args.append("elixir=%s" % self.elixir) 397 cmd_args.append("sqlobject=%s" % self.sqlobject) 398 cmd_args.append("identity=%s" % self.identity) 399 cmd_args.append("package=%s" % self.package) 400 # set the exact ORM-version for the proper requirements 401 # it's extracted from our own requirements, so looking 402 # them up must be in sync (there must be the extras_require named sqlobject/sqlalchemy) 403 if self.sqlobject: 404 sqlobjectversion = str(get_requirement('sqlobject')) 405 cmd_args.append("sqlobjectversion=%s" % sqlobjectversion) 406 407 if self.sqlalchemy: 408 sqlalchemyversion = str(get_requirement('sqlalchemy')) 409 cmd_args.append("sqlalchemyversion=%s" % sqlalchemyversion) 410 411 if self.elixir: 412 elixirversion = str(get_requirement('sqlalchemy', 'elixir')) 413 cmd_args.append("elixirversion=%s" % elixirversion) 414 415 command.run(cmd_args) 416 417 startscript = "start-%s.py" % self.package 418 if os.path.exists(startscript): 419 oldmode = os.stat(startscript).st_mode 420 os.chmod(startscript, 421 oldmode | stat.S_IXUSR) 422 sys.argv = ["setup.py", "egg_info"] 423 import imp 424 imp.load_module("setup", *imp.find_module("setup", ["."])) 425 426 # dirty hack to allow "empty" dirs 427 for base, path, files in os.walk("./"): 428 for file in files: 429 if file == "empty": 430 os.remove(os.path.join(base, file))
431