# HG changeset patch # User Todd Larsen # Date 1213055360 0 # Node ID 39e1c8a54b376806a358f13f14b2f2cd21b3e08c # Parent a237c3c5763e5546e4e7b4a59211e8d14bcf34fe Addressed Sverre's commits on the previous commit. Patch by: Todd Larsen Review by: Sverre Rabbelier Review issue: 282 Review URL: http://codereviews.googleopensourceprograms.com/282 diff -r a237c3c5763e -r 39e1c8a54b37 scripts/app_image.py --- a/scripts/app_image.py Fri Jun 06 04:30:49 2008 +0000 +++ b/scripts/app_image.py Mon Jun 09 23:49:20 2008 +0000 @@ -15,6 +15,61 @@ # limitations under the License. """Functions used by multiple scripts to form Google App Engine images. + +These utility functions are used by multiple scripts for creating and managing +Google App Engine "uploadable image" directories produced by combining a +specific Melange application (for example: trunk/apps/proto, trunk/apps/gsoc, +trunk/apps/ghop, etc.), the SoC framework in trunk/soc, and any /thirdparty/ +packages, such as thirdparty/django. + +The directory layout expected by Google App Engine is (approximately): + / + app.yaml + index.yaml + content/ (a static content directory for the Melange application) + main.py (a WSGI wrapper for Django-based Google App Engine apps) + settings.py (application-specific Django settings) + urls.py (application-specific URL handler mappings) + +The application itself can have application-specific code and templates, so +there is an additional subdirectory with the same name as the application +(to disambiguate modules in the Melange application with same-named modules +in the SoC framework): + / + / + models/, templates/, views/, etc. + +Google App Engine assumes that the root of package paths is /, so all +packages are placed in sub-directories of /, and the SoC framework +is considered a package: + / + soc/ + models/, templates/, views/, etc. + +For Django template based applications (which Melange applications are), +include the django distribution directory (which is one of the /thirdparty/ +packages) and some Django-specific files: + / + django/ + core/, db/, dispatch/, etc. + +Any other /thirdparty/ packages would be included in the the Google App Engine +"uploadable image" directory similarly to Django above. + + +A NOTE ABOUT DIRECTORY NAMES RETURNED BY FUNCTIONS IN THIS MODULE + +The functions in this module return directory names with a trailing / svn path +separator. This is done by convention only (svn_helper functions normalize +the path names of directories in this same way). The trailing separator is +kept to make it easier to combine paths (since the caller can always assume +directories end with the / separator) and to make it easier to distinguish +directories from files in human-readable output. + +Some pysvn Client methods accept directories named this way, others raise +exceptions and expect a "canonical" form that does not include the trailing +/ separator. This does not seem to be documented in the pysvn documentation, +so the trailing separator is removed in svn_helper when necessary. """ __authors__ = [ @@ -23,37 +78,71 @@ ] +import sys + from trunk.scripts import svn_helper def getRepoAppPath(repo, app): """Returns path to specified Melange app in the supplied svn repository. + + Args: + repo: SVN repository URL + app: Melange application name (expected to exist in trunk/apps) """ - return '%strunk/apps/%s' % (repo, app) + # see note about directory names ending with / svn path separators in the + # module __doc__ string + return svn_helper.formatDirPath('%strunk/apps/%s' % ( + svn_helper.formatDirPath(repo), app)) def getRepoThirdPartyPath(repo): """Returns path to third-party packages in the supplied svn repository. + + Args: + repo: SVN repository URL """ - return '%sthirdparty/' % repo + # see note about directory names ending with / svn path separators in the + # module __doc__ string + return '%sthirdparty/' % svn_helper.formatDirPath(repo) -def getThirdPartyPackageNames(pkg_path, **kwargs): +def getThirdPartyPackageNames(pkg_path, **svn_kwargs): """Returns a list of third-party packages in the supplied URL. + + Args: + pkg_path: full SVN URL path to the directory containing third-party + packages, usually the path formed by calling getRepoThirdPartyPath() + **svn_kwargs: keyword arguments passed through to svn_helper.lsDirs() + (for "advanced users") + + Returns: + A list of third-party packages found in pkg_path. Third-party "packages" + are all of the directories is the pkg_path directory (but not individual + files in pkg_path) that do *not* begin with an underscore (_). Individual + files and directories beginning with underscores in the pkg_path directory + are omitted from the results. """ - return [pkg for pkg in svn_helper.lsDirs(pkg_path, **kwargs) + return [pkg for pkg in svn_helper.lsDirs(pkg_path, **svn_kwargs) if not pkg.startswith('_')] def getRepoFrameworksPath(repo): """Returns path to Melange framework packages in the supplied svn repository. + + Args: + repo: SVN repository URL """ - return '%strunk/' % repo + # see note about directory names ending with / svn path separators in the + # module __doc__ string + return '%strunk/' % svn_helper.formatDirPath(repo) def getFrameworksNames(): - """Returns a list of Melange framework packages (currently a static list). + """Returns a list of Melange framework packages (currently a constant list). """ + # see note about directory names ending with / svn path separators in the + # module __doc__ string return ['soc/'] @@ -71,16 +160,41 @@ Returns: * branch if it was specified ("non-False"), or - * users/user/dest if dest was specified, or - * users/user/src otherwise + * users/user/dest/ if dest was specified, or + * users/user/src/ otherwise """ if not branch: if dest: - branch = 'users/%s%s' % (user, dest) + branch = 'users/%s%s' % (svn_helper.formatDirPath(user), dest) else: - branch = 'users/%s%s' % (user, src) + branch = 'users/%s%s' % (svn_helper.formatDirPath(user), src) + + return svn_helper.formatDirPath(branch) + + +def verbosePrint(verbose, fmt_str, *fmt_args, **fmt_kwargs): + """If verbosity level greater than zero, print out formatted string. + + Since app_image.py is a utility module most often used by scripts, many + of its functions print to stdout. For cases when printed output may not + be desired, functions should supply a 'verbose' parameter to disable + output. The functions in app_image.py use this function to implement + that selective printing capability. - return branch + Args: + verbose: verbosity level integer, any value greater than 0 enables + output + fmt_str: required format string + *fmt_args: if present, positional arguments supplied to fmt_str + **fmt_kwargs: if *fmt_args is not present, named arguments supplied to + fmt_str, which is expected to contain named format specifiers, for + example: '%(foo)s' + """ + if verbose > 0: + if not fmt_args: + fmt_args = fmt_kwargs + + print fmt_str % fmt_args def branchFromSrcApp(app, repo, dest, verbose=1, **svn_kwargs): @@ -95,8 +209,8 @@ """ repo_app = getRepoAppPath(repo, app) - if verbose > 0: - print 'Branching %s from:\n %s\nto:\n %s\n' % (app, repo_app, dest) + verbosePrint(verbose, 'Branching %s from:\n %s\nto:\n %s\n', + app, repo_app, dest) svn_helper.branchDir(repo_app, dest, **svn_kwargs) @@ -119,9 +233,9 @@ pkg_dir = getRepoThirdPartyPath(repo) packages = getThirdPartyPackageNames(pkg_dir) - if verbose > 0: - print 'Branching third-party packages:\n %s\nfrom:\n %s\ninto:\n %s\n' % ( - ' '.join(packages), pkg_dir, dest) + verbosePrint(verbose, + 'Branching third-party packages:\n %s\nfrom:\n %s\ninto:\n %s\n', + ' '.join(packages), pkg_dir, dest) svn_helper.branchItems(pkg_dir, dest, packages, **svn_kwargs) @@ -140,8 +254,8 @@ framework_dir = getRepoFrameworksPath(repo) packages = getFrameworksNames() - if verbose > 0: - print 'Branching framework components:\n %s\nfrom:\n %s\ninto:\n %s\n' % ( + verbosePrint(verbose, + 'Branching framework components:\n %s\nfrom:\n %s\ninto:\n %s\n', ' '.join(packages), framework_dir, dest) svn_helper.branchItems(framework_dir, dest, packages, **svn_kwargs) @@ -159,8 +273,8 @@ """ repo_app = getRepoAppPath(repo, app) - if verbose > 0: - print 'Exporting %s from:\n %s\nto:\n %s\n' % (app, repo_app, dest) + verbosePrint(verbose, 'Exporting %s from:\n %s\nto:\n %s\n', + app, repo_app, dest) svn_helper.exportDir(repo_app, dest, **svn_kwargs) @@ -183,9 +297,9 @@ pkg_dir = getRepoThirdPartyPath(repo) packages = getThirdPartyPackageNames(pkg_dir) - if verbose > 0: - print 'Exporting third-party packages:\n %s\nfrom:\n %s\ninto:\n %s\n' % ( - ' '.join(packages), pkg_dir, dest) + verbosePrint(verbose, + 'Exporting third-party packages:\n %s\nfrom:\n %s\ninto:\n %s\n', + ' '.join(packages), pkg_dir, dest) svn_helper.exportItems(pkg_dir, dest, packages, **svn_kwargs) @@ -204,8 +318,8 @@ framework_dir = getRepoFrameworksPath(repo) packages = getFrameworksNames() - if verbose > 0: - print 'Exporting framework components:\n %s\nfrom:\n %s\ninto:\n %s\n' % ( - ' '.join(packages), framework_dir, dest) + verbosePrint(verbose, + 'Exporting framework components:\n %s\nfrom:\n %s\ninto:\n %s\n', + ' '.join(packages), framework_dir, dest) svn_helper.exportItems(framework_dir, dest, packages, **svn_kwargs)