diff --git a/setup.py b/setup.py index 9cb496b..0a0fa79 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,8 @@ import sys from setuptools import setup, find_packages +py3k = sys.version_info >= (3,) + version = '1.0b5-dev' long_description = ( @@ -14,9 +16,19 @@ open('CHANGES.txt').read() + '\n') -tests_require = [ - 'unittest2', - 'Cheetah'], +if py3k: + tests_require = [] + requires = [ + 'setuptools', + ] +else: + tests_require = [ + 'unittest2', + 'Cheetah'] + requires = [ + 'setuptools', + "Cheetah>1.0,<=2.2.1", + ] setup(name='templer.core', version=version, @@ -54,10 +66,7 @@ include_package_data=True, platforms='Any', zip_safe=False, - install_requires=[ - 'setuptools', - "Cheetah>1.0,<=2.2.1", - ], + install_requires=requires, tests_require=tests_require, extras_require=dict(test=tests_require), entry_points=""" diff --git a/src/templer/core/base.py b/src/templer/core/base.py index 4ce35d7..1966a4a 100644 --- a/src/templer/core/base.py +++ b/src/templer/core/base.py @@ -1,11 +1,16 @@ +from __future__ import print_function import os import sys import pkg_resources from copy import copy from textwrap import TextWrapper -import ConfigParser -from ConfigParser import SafeConfigParser +#import ConfigParser +#from ConfigParser import SafeConfigParser +from templer.core.compat import ( + ConfigParser, + SafeConfigParser, +) from templer.core import pluginlib from templer.core import copydir @@ -39,8 +44,8 @@ def wrap_help_paras(wrapper, text): for idx, para in enumerate(text.split("\n\n")): if idx: - print - print wrapper.fill(para) + print() + print(wrapper.fill(para)) def get_zopeskel_prefs(): @@ -176,7 +181,7 @@ def read_vars(self, command=None): def write_files(self, command, output_dir, vars): template_dir = self.template_dir() if not os.path.exists(output_dir): - print "Creating directory %s" % output_dir + print("Creating directory %s" % output_dir) if not command.simulate: # Don't let copydir create this top-level directory, # since copydir will svn add it sometimes: @@ -294,8 +299,8 @@ def print_subtemplate_notice(self, output_dir=None): print_commands.append(' %s %s' % (name, this_command.load().summary)) print_commands = '\n'.join(print_commands) - print '-' * 78 - print """\ + print('-' * 78) + print("""\ The project you just created has local commands. These can be used from within the product. @@ -304,8 +309,8 @@ def print_subtemplate_notice(self, output_dir=None): Commands: %s -For more information: paster help COMMAND""" % print_commands - print '-' * 78 +For more information: paster help COMMAND""" % print_commands) + print('-' * 78) def print_zopeskel_message(self, msg_name): """ print a message stored as an attribute of the template @@ -316,9 +321,9 @@ def print_zopeskel_message(self, msg_name): initial_indent="** ", subsequent_indent="** ", ) - print "\n" + '*'*74 + print("\n" + '*'*74) wrap_help_paras(textwrapper, msg) - print '*'*74 + "\n" + print('*'*74 + "\n") def readable_license_options(self): output = ["The following licenses are available:\n", ] @@ -520,8 +525,8 @@ def check_vars(self, vars, cmd): if response is not self.null_value_marker: try: response = var.validate(response) - except ValidationException, e: - print e + except ValidationException as e: + print(e) response = self.null_value_marker elif var.default is NoDefault: errors.append('Required variable missing: %s' diff --git a/src/templer/core/compat.py b/src/templer/core/compat.py new file mode 100644 index 0000000..bdb35df --- /dev/null +++ b/src/templer/core/compat.py @@ -0,0 +1,15 @@ +import sys +inPy3k = sys.version_info[0] == 3 + +if not inPy3k: + import ConfigParser + from ConfigParser import SafeConfigParser + import StringIO + maxint = sys.maxint + string_types = basestring +else: + import configparser as ConfigParser + from configparser import ConfigParser as SafeConfigParser + import io as StringIO + maxint = sys.maxsize + string_types = (str, bytes) diff --git a/src/templer/core/control_script.py b/src/templer/core/control_script.py index b0e19ee..61bfbbc 100644 --- a/src/templer/core/control_script.py +++ b/src/templer/core/control_script.py @@ -1,13 +1,18 @@ +from __future__ import print_function import sys import os -import ConfigParser import pkg_resources -from cStringIO import StringIO from textwrap import TextWrapper from templer.core.base import wrap_help_paras from templer.core.create import CreateDistroCommand from templer.core.ui import list_sorted_templates +from templer.core.compat import ConfigParser +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO + try: from templer.localcommands.command import TemplerLocalCommand @@ -303,10 +308,10 @@ def __call__(self, argv): """ try: template_name, output_name, args = self._process_args(argv) - except SyntaxError, e: + except SyntaxError as e: self.usage() msg = "ERROR: There was a problem with your arguments: %s\n" - print msg % str(e) + print(msg % str(e)) raise rez = pkg_resources.iter_entry_points( @@ -315,14 +320,14 @@ def __call__(self, argv): rez = list(rez) if not rez: self.usage() - print "ERROR: No such template: %s\n" % template_name + print("ERROR: No such template: %s\n" % template_name) return 1 template = rez[0].load() - print "\n%s: %s" % (template_name, template.summary) + print("\n%s: %s" % (template_name, template.summary)) help = getattr(template, 'help', None) if help: - print template.help + print(template.help) command = CreateDistroCommand() @@ -339,44 +344,44 @@ def __call__(self, argv): if output_name: try: self._checkdots(template, output_name) - except ValueError, e: - print "ERROR: %s\n" % str(e) + except ValueError as e: + print("ERROR: %s\n" % str(e)) raise else: ndots = getattr(template, 'ndots', None) help = DOT_HELP.get(ndots) while True: if help: - print help + print(help) try: challenge = "Enter project name (or q to quit)" output_name = command.challenge(challenge) if output_name == 'q': - print "\n\nExiting...\n" + print("\n\nExiting...\n") return 0 self._checkdots(template, output_name) - except ValueError, e: - print "\nERROR: %s" % e + except ValueError as e: + print("\nERROR: %s" % e) raise else: break - print self.texts['help_prompt'] + print(self.texts['help_prompt']) try: command.run(['-q', '-t', template_name] + args + special_args) except KeyboardInterrupt: - print "\n\nExiting...\n" + print("\n\nExiting...\n") return 0 - except Exception, e: - print "\nERROR: %s\n" % str(e) + except Exception as e: + print("\nERROR: %s\n" % str(e)) raise return 0 # Public API methods, can be overridden by templer-based applications def show_help(self): """display help text""" - print self.texts['description'] % {'script_name': self.name} + print(self.texts['description'] % {'script_name': self.name}) return 0 def generate_dotfile(self): @@ -384,14 +389,14 @@ def generate_dotfile(self): """ cats = list_sorted_templates(scope=self.allowed_packages) - print self.texts['dotfile_header'] % {'script_name': self.name} + print(self.texts['dotfile_header'] % {'script_name': self.name}) for temp in sum(cats.values(), []): - print "\n[%(name)s]\n" % temp + print("\n[%(name)s]\n" % temp) tempc = temp['entry'].load() for var in tempc.vars: if hasattr(var, 'pretty_description'): - print "# %s" % var.pretty_description() - print "# %s = %s\n" % (var.name, var.default) + print("# %s" % var.pretty_description()) + print("# %s = %s\n" % (var.name, var.default)) return 0 def list_verbose(self): @@ -402,22 +407,22 @@ def list_verbose(self): cats = list_sorted_templates(scope=self.allowed_packages) if cats: for title, items in cats.items(): - print "\n"+ title - print "-" * len(title) + print("\n"+ title) + print("-" * len(title)) # Hard-coded for now, since 'add' is the only one if title == 'Local Commands': - print '\nadd: Allows the addition of further templates'\ - ' from the following list' - print ' to an existing package\n' - print '\nLocal Templates' - print '-----------------' + print('\nadd: Allows the addition of further templates'\ + ' from the following list') + print(' to an existing package\n') + print('\nLocal Templates') + print('-----------------') for temp in items: - print "\n%s: %s\n" % (temp['name'], temp['summary']) + print("\n%s: %s\n" % (temp['name'], temp['summary'])) if temp['help']: wrap_help_paras(textwrapper, temp['help']) - print + print() else: - print self.texts['not_here_warning'] + print(self.texts['not_here_warning']) return 0 @@ -425,8 +430,8 @@ def show_version(self): """show installed version of packages listed in self.versions """ version_info = self._get_version_info() - print self._format_version_info( - version_info, "Installed Templer Packages") + print(self._format_version_info( + version_info, "Installed Templer Packages")) return 0 def usage(self): @@ -437,14 +442,14 @@ def usage(self): if self.allowed_packages in ['all', 'local']: local = '[] ' - print self.texts['usage'] % {'templates': templates, + print(self.texts['usage'] % {'templates': templates, 'local': local, 'script_name': self.name, - 'dotfile_name': self.dotfile} + 'dotfile_name': self.dotfile}) return 0 def no_locals(self): - print self.texts['no_localcommands_warning'] + print(self.texts['no_localcommands_warning']) # Private API supporting command-line flags # should not need to be changed by templer-based applications @@ -461,7 +466,7 @@ def _run_localcommand(self, args): return result else: # situation 1, fail and report. - print self.texts['no_localcommands_warning'] + print(self.texts['no_localcommands_warning']) return 1 def _get_templer_packages(self): @@ -490,12 +495,12 @@ def _format_version_info(self, version_info, header=None): maxpkg = max([len(vi[0]) for vi in version_info]) maxver = max([len(vi[1]) for vi in version_info]) if header is not None: - print >>s, "\n| %s" % header - print >>s, "+" + ("-" * (maxpkg + maxver + 3)) + print("\n| %s" % header, file=s) + print("+" + ("-" * (maxpkg + maxver + 3)), file=s) for vi in version_info: padding = maxpkg - len(vi[0]) values = [vi[0], ' ' * padding, vi[1]] - print >>s, "| %s:%s %s" % tuple(values) + print("| %s:%s %s" % tuple(values), file=s) s.seek(0) return s.read() @@ -509,19 +514,19 @@ def _list_printable_templates(self): templates = sum(cats.values(), []) # flatten into single list max_name = max([len(x['name']) for x in templates]) for title, items in cats.items(): - print >>s, "\n%s\n" % title + print("\n%s\n" % title, file=s) # Hard-coded for now, since 'add' is the only one if title == 'Local Commands': - print >>s, "| add: Allows the addition of further"\ - " templates from the following list" - print >>s, " to an existing package\n" + print("| add: Allows the addition of further"\ + " templates from the following list", file=s) + print(" to an existing package\n", file=s) for entry in items: - print >>s, "| %s:%s %s\n" % ( + print("| %s:%s %s\n" % ( entry['name'], ' '*(max_name-len(entry['name'])), - entry['summary']), + entry['summary']), file=s) else: - print >>s, self.texts['not_here_warning'] + print(self.texts['not_here_warning'], file=s) s.seek(0) return s.read() @@ -610,7 +615,7 @@ def _context_awareness(self): f = open(changes_txt, 'rb') content = f.read() f.close() - if 'Package created using templer' in content: + if b'Package created using templer' in content: made_by_templer = True (cwd, tail) = os.path.split(cwd) diff --git a/src/templer/core/copydir.py b/src/templer/core/copydir.py index 39ffc3f..140d344 100644 --- a/src/templer/core/copydir.py +++ b/src/templer/core/copydir.py @@ -1,3 +1,4 @@ +from __future__ import print_function # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php @@ -8,7 +9,11 @@ import string import urllib -import Cheetah.Template +try: + import Cheetah.Template + no_cheetah = False +except ImportError: + no_cheetah = True class SkipTemplate(Exception): @@ -72,11 +77,11 @@ def copy_dir(source, pad = ' ' * (indent * 2) if not os.path.exists(dest): if verbosity >= 1: - print '%sCreating %s/' % (pad, dest) + print('%sCreating %s/' % (pad, dest)) if not simulate: makedirs(dest, verbosity=verbosity, pad=pad) elif verbosity >= 2: - print '%sDirectory %s exists' % (pad, dest) + print('%sDirectory %s exists' % (pad, dest)) for name in names: if use_pkg_resources: @@ -87,7 +92,7 @@ def copy_dir(source, if reason: if verbosity >= 2: reason = pad + reason % {'filename': full} - print reason + print(reason) continue if sub_vars: dest_full = os.path.join(dest, substitute_filename(name, vars)) @@ -97,7 +102,7 @@ def copy_dir(source, sub_file = sub_vars if use_pkg_resources and pkg_resources.resource_isdir(source[0], full): if verbosity: - print '%sRecursing into %s' % (pad, os.path.basename(full)) + print('%sRecursing into %s' % (pad, os.path.basename(full))) copy_dir((source[0], full), dest_full, vars, verbosity, simulate, indent=indent + 1, use_cheetah=use_cheetah, sub_vars=sub_vars, interactive=interactive, @@ -105,7 +110,7 @@ def copy_dir(source, continue elif not use_pkg_resources and os.path.isdir(full): if verbosity: - print '%sRecursing into %s' % (pad, os.path.basename(full)) + print('%sRecursing into %s' % (pad, os.path.basename(full))) copy_dir(full, dest_full, vars, verbosity, simulate, indent=indent + 1, use_cheetah=use_cheetah, sub_vars=sub_vars, interactive=interactive, @@ -133,7 +138,7 @@ def copy_dir(source, f.close() if old_content == content: if verbosity: - print '%s%s already exists (same content)' % (pad, dest_full) + print('%s%s already exists (same content)' % (pad, dest_full)) continue if interactive: if not query_interactive( @@ -143,9 +148,9 @@ def copy_dir(source, elif not overwrite: continue if verbosity and use_pkg_resources: - print '%sCopying %s to %s' % (pad, full, dest_full) + print('%sCopying %s to %s' % (pad, full, dest_full)) elif verbosity: - print '%sCopying %s to %s' % (pad, os.path.basename(full), dest_full) + print('%sCopying %s to %s' % (pad, os.path.basename(full), dest_full)) if not simulate: f = open(dest_full, 'wb') f.write(content) @@ -198,9 +203,9 @@ def query_interactive(src_fn, dest_fn, src_content, dest_content, msg = '; %i lines removed' % (removed - added) else: msg = '' - print 'Replace %i bytes with %i bytes (%i/%i lines changed%s)' % ( + print('Replace %i bytes with %i bytes (%i/%i lines changed%s)' % ( len(dest_content), len(src_content), - removed, len(dest_content.splitlines()), msg) + removed, len(dest_content.splitlines()), msg)) prompt = 'Overwrite %s [y/n/d/B/?] ' % dest_fn while 1: if all_answer is None: @@ -214,14 +219,14 @@ def query_interactive(src_fn, dest_fn, src_content, dest_content, while os.path.exists(new_dest_fn): n += 1 new_dest_fn = dest_fn + '.bak' + str(n) - print 'Backing up %s to %s' % (dest_fn, new_dest_fn) + print('Backing up %s to %s' % (dest_fn, new_dest_fn)) if not simulate: shutil.copyfile(dest_fn, new_dest_fn) return True elif response.startswith('all '): rest = response[4:].strip() if not rest or rest[0] not in ('y', 'n', 'b'): - print query_usage + print(query_usage) continue response = all_answer = rest[0] if response[0] == 'y': @@ -229,11 +234,11 @@ def query_interactive(src_fn, dest_fn, src_content, dest_content, elif response[0] == 'n': return False elif response == 'dc': - print '\n'.join(c_diff) + print('\n'.join(c_diff)) elif response[0] == 'd': - print '\n'.join(u_diff) + print('\n'.join(u_diff)) else: - print query_usage + print(query_usage) query_usage = """\ Responses: @@ -270,9 +275,11 @@ def substitute_content(content, vars, filename='', tmpl = LaxTemplate(content) try: return tmpl.substitute(TypeMapper(v)) - except Exception, e: + except Exception as e: _add_except(e, ' in file %s' % filename) raise + if no_cheetah: + raise Exception("In python3, Cheetah template is not supported.") tmpl = Cheetah.Template.Template(source=content, searchList=[vars]) return careful_sub(tmpl, vars, filename) @@ -302,18 +309,18 @@ def sub_catcher(filename, vars, func, *args, **kw): """ try: return func(*args, **kw) - except SkipTemplate, e: - print 'Skipping file %s' % filename + except SkipTemplate as e: + print('Skipping file %s' % filename) if str(e): - print str(e) + print(str(e)) raise - except Exception, e: - print 'Error in file %s:' % filename + except Exception as e: + print('Error in file %s:' % filename) if isinstance(e, NameError): items = vars.items() items.sort() for name, value in items: - print '%s = %r' % (name, value) + print('%s = %r' % (name, value)) raise @@ -397,7 +404,7 @@ def __getitem__(self, item): def eval_with_catch(expr, vars): try: return eval(expr, vars) - except Exception, e: + except Exception as e: _add_except(e, 'in expression %r' % expr) raise diff --git a/src/templer/core/create.py b/src/templer/core/create.py index a2988d4..1629fc2 100644 --- a/src/templer/core/create.py +++ b/src/templer/core/create.py @@ -1,7 +1,11 @@ +from __future__ import print_function # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -import ConfigParser +#import ConfigParser +from templer.core.compat import ( + ConfigParser, +) import difflib import fnmatch import getpass @@ -180,17 +184,17 @@ def ask(self, prompt, safe=False, default=True): response = raw_input(prompt).strip().lower() if not response: if default in ('careful', 'none'): - print 'Please enter yes or no' + print('Please enter yes or no') continue return default if default == 'careful': if response in ('yes', 'no'): return response == 'yes' - print 'Please enter "yes" or "no"' + print('Please enter "yes" or "no"') continue if response[0].lower() in ('y', 'n'): return response[0].lower() == 'y' - print 'Y or N please' + print('Y or N please') def challenge(self, prompt, default=NoDefault, should_echo=True): """ @@ -303,12 +307,12 @@ def ensure_dir(self, dir): if not os.path.exists(dir): self.ensure_dir(os.path.dirname(dir)) if self.verbose: - print 'Creating %s' % self.shorten(dir) + print('Creating %s' % self.shorten(dir)) if not self.simulate: os.mkdir(dir) else: if self.verbose > 1: - print "Directory already exists: %s" % self.shorten(dir) + print("Directory already exists: %s" % self.shorten(dir)) def ensure_file(self, filename, content): """ @@ -321,7 +325,7 @@ def ensure_file(self, filename, content): self.ensure_dir(os.path.dirname(filename)) if not os.path.exists(filename): if self.verbose: - print 'Creating %s' % filename + print('Creating %s' % filename) if not self.simulate: f = open(filename, 'wb') f.write(content) @@ -332,16 +336,16 @@ def ensure_file(self, filename, content): f.close() if content == old_content: if self.verbose > 1: - print 'File %s matches expected content' % filename + print('File %s matches expected content' % filename) return if not self.options.overwrite: - print 'Warning: file %s does not match expected content' % filename + print('Warning: file %s does not match expected content' % filename) diff = difflib.context_diff( content.splitlines(), old_content.splitlines(), 'expected ' + filename, filename) - print '\n'.join(diff) + print('\n'.join(diff)) if self.interactive: while 1: s = raw_input( @@ -352,12 +356,12 @@ def ensure_file(self, filename, content): break if s.startswith('n'): return - print 'Unknown response; Y or N please' + print('Unknown response; Y or N please') else: return if self.verbose: - print 'Overwriting %s with new content' % filename + print('Overwriting %s with new content' % filename) if not self.simulate: f = open(filename, 'wb') f.write(content) @@ -382,8 +386,8 @@ def insert_into_file(self, filename, marker_name, text, # If we are doing a simulation, it's expected that some # files won't exist... if self.verbose: - print 'Would (if not simulating) insert text into %s' % ( - self.shorten(filename)) + print('Would (if not simulating) insert text into %s' % ( + self.shorten(filename))) return f = open(filename) @@ -397,8 +401,8 @@ def insert_into_file(self, filename, marker_name, text, if (lines[i:] and len(lines[i:]) > 1 and ''.join(lines[i + 1:]).strip().startswith(text.strip())): # Already have it! - print 'Warning: line already found in %s (not inserting' % filename - print ' %s' % lines[i] + print('Warning: line already found in %s (not inserting' % filename) + print(' %s' % lines[i]) return if indent: @@ -412,11 +416,11 @@ def insert_into_file(self, filename, marker_name, text, "Marker '-*- %s -*-' not found in %s" % (marker_name, filename)) if 1 or self.simulate: # @@: being permissive right now - print 'Warning: %s' % errstr + print('Warning: %s' % errstr) else: raise ValueError(errstr) if self.verbose: - print 'Updating %s' % self.shorten(filename) + print('Updating %s' % self.shorten(filename)) if not self.simulate: f = open(filename, 'w') f.write(''.join(lines)) @@ -462,7 +466,7 @@ def run_command(self, cmd, *args, **kw): cwd=cwd, stderr=stderr_pipe, stdout=subprocess.PIPE) - except OSError, e: + except OSError as e: if e.errno != 2: # File not found raise @@ -470,27 +474,27 @@ def run_command(self, cmd, *args, **kw): "The expected executable %s was not found (%s)" % (cmd, e)) if self.verbose: - print 'Running %s %s' % (cmd, ' '.join(args)) + print('Running %s %s' % (cmd, ' '.join(args))) if simulate: return None stdout, stderr = proc.communicate() if proc.returncode and not expect_returncode: if not self.verbose: - print 'Running %s %s' % (cmd, ' '.join(args)) - print 'Error (exit code: %s)' % proc.returncode + print('Running %s %s' % (cmd, ' '.join(args))) + print('Error (exit code: %s)' % proc.returncode) if stderr: - print stderr + print(stderr) raise OSError("Error executing command %s" % cmd) if self.verbose > 2: if stderr: - print 'Command error output:' - print stderr + print('Command error output:') + print(stderr) if stdout: - print 'Command output:' - print stdout + print('Command output:') + print(stdout) elif proc.returncode and warn_returncode: - print 'Warning: command failed (%s %s)' % (cmd, ' '.join(args)) - print 'Exited with code %s' % proc.returncode + print('Warning: command failed (%s %s)' % (cmd, ' '.join(args))) + print('Exited with code %s' % proc.returncode) return stdout def quote_first_command_arg(self, arg): @@ -534,17 +538,17 @@ def write_file(self, filename, content, source=None, f.close() if content == old_content: if self.verbose: - print 'File %s exists with same content' % ( - self.shorten(filename)) + print('File %s exists with same content' % ( + self.shorten(filename))) return if (not self.simulate and self.options.interactive): if not self.ask('Overwrite file %s?' % filename): return if self.verbose > 1 and source: - print 'Writing %s from %s' % (self.shorten(filename), - self.shorten(source)) + print('Writing %s from %s' % (self.shorten(filename), + self.shorten(source))) elif self.verbose: - print 'Writing %s' % self.shorten(filename) + print('Writing %s' % self.shorten(filename)) if not self.simulate: already_existed = os.path.exists(filename) if binary: @@ -689,13 +693,13 @@ def command(self): if self.options.list_variables: return self.list_variables(templates) if self.verbose: - print 'Selected and implied templates:' + print('Selected and implied templates:') max_tmpl_name = max([len(tmpl_name) for tmpl_name, tmpl in templates]) for tmpl_name, tmpl in templates: - print ' %s%s %s' % ( + print(' %s%s %s' % ( tmpl_name, ' '*(max_tmpl_name-len(tmpl_name)), - tmpl.summary) - print + tmpl.summary)) + print() if not self.args: if self.interactive: dist_name = self.challenge('Enter project name') @@ -760,7 +764,7 @@ def command(self): def create_template(self, template, output_dir, vars): if self.verbose: - print 'Creating template %s' % template.name + print('Creating template %s' % template.name) template.run(self, output_dir, vars) ignore_egg_info_files = [ @@ -810,30 +814,30 @@ def all_entry_points(self): def display_vars(self, vars): vars = vars.items() vars.sort() - print 'Variables:' + print('Variables:') max_var = max([len(n) for n, v in vars]) for name, value in vars: - print ' %s:%s %s' % ( - name, ' '*(max_var-len(name)), value) + print(' %s:%s %s' % ( + name, ' '*(max_var-len(name)), value)) def list_templates(self): templates = [] for entry in self.all_entry_points(): try: templates.append(entry.load()(entry.name)) - except Exception, e: + except Exception as e: # We will not be stopped! - print 'Warning: could not load entry point %s (%s: %s)' % ( - entry.name, e.__class__.__name__, e) + print('Warning: could not load entry point %s (%s: %s)' % ( + entry.name, e.__class__.__name__, e)) max_name = max([len(t.name) for t in templates]) templates.sort(lambda a, b: cmp(a.name, b.name)) - print 'Available templates:' + print('Available templates:') for template in templates: # @@: Wrap description - print ' %s:%s %s' % ( + print(' %s:%s %s' % ( template.name, ' '*(max_name-len(template.name)), - template.summary) + template.summary)) def inspect_files(self, output_dir, templates, vars): file_sources = {} @@ -881,7 +885,7 @@ def _show_files(self, output_dir, file_sources, join='', indent=0): for ext in self._ignore_filenames: if fnmatch.fnmatch(name, ext): if self.verbose > 1: - print '%sIgnoring %s' % (pad, name) + print('%sIgnoring %s' % (pad, name)) skip_this = True break if skip_this: @@ -889,16 +893,16 @@ def _show_files(self, output_dir, file_sources, join='', indent=0): partial = os.path.join(join, name) if partial not in file_sources: if self.verbose > 1: - print '%s%s (not from template)' % (pad, name) + print('%s%s (not from template)' % (pad, name)) continue templates = file_sources.pop(partial) - print '%s%s from:' % (pad, name) + print('%s%s from:' % (pad, name)) for template in templates: - print '%s %s' % (pad, template.name) + print('%s %s' % (pad, template.name)) for dir in dirs: if dir in self._ignore_dirs: continue - print '%sRecursing into %s/' % (pad, dir) + print('%sRecursing into %s/' % (pad, dir)) self._show_files( output_dir, file_sources, join=os.path.join(join, dir), @@ -907,15 +911,15 @@ def _show_files(self, output_dir, file_sources, join='', indent=0): def _show_leftovers(self, output_dir, file_sources): if not file_sources: return - print - print 'These files were supposed to be generated by templates' - print 'but were not found:' + print() + print('These files were supposed to be generated by templates') + print('but were not found:') file_sources = file_sources.items() file_sources.sort() for partial, templates in file_sources: - print ' %s from:' % partial + print(' %s from:' % partial) for template in templates: - print ' %s' % template.name + print(' %s' % template.name) def list_variables(self, templates): for tmpl_name, tmpl in templates: @@ -928,10 +932,10 @@ def list_variables(self, templates): def _show_template_vars(self, tmpl_name, tmpl, message=None): title = '%s (from %s)' % (tmpl.name, tmpl_name) - print title - print '-' * len(title) + print(title) + print('-' * len(title)) if message is not None: - print ' %s' % message - print + print(' %s' % message) + print() return tmpl.print_vars(indent=2) diff --git a/src/templer/core/pluginlib.py b/src/templer/core/pluginlib.py index f19efe5..83ebcf8 100644 --- a/src/templer/core/pluginlib.py +++ b/src/templer/core/pluginlib.py @@ -10,7 +10,7 @@ def resolve_plugins(plugin_list): plugin = plugin_list.pop() try: pkg_resources.require(plugin) - except pkg_resources.DistributionNotFound, e: + except pkg_resources.DistributionNotFound as e: msg = '%sNot Found%s: %s (did you run python setup.py develop?)' if str(e) != plugin: e.args = (msg % (str(e) + ': ', ' for', plugin)), diff --git a/src/templer/core/structures.py b/src/templer/core/structures.py index ecb59f2..9693578 100644 --- a/src/templer/core/structures.py +++ b/src/templer/core/structures.py @@ -1,3 +1,4 @@ +from __future__ import print_function import sys import os @@ -29,7 +30,7 @@ def write_files(self, command, output_dir, vars): structure_dirs = self.structure_dir() if len(structure_dirs) > 0: if not os.path.exists(output_dir): - print "Creating directory %s" % output_dir + print("Creating directory %s" % output_dir) if not command.simulate: os.makedirs(output_dir) for structure_dir in structure_dirs: diff --git a/src/templer/core/tests/test_base.py b/src/templer/core/tests/test_base.py index fc53ac1..dfbb005 100644 --- a/src/templer/core/tests/test_base.py +++ b/src/templer/core/tests/test_base.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest from templer.core.base import BaseTemplate, get_var from templer.core.create import CreateDistroCommand diff --git a/src/templer/core/tests/test_licenses.py b/src/templer/core/tests/test_licenses.py index 9139b17..c06a050 100644 --- a/src/templer/core/tests/test_licenses.py +++ b/src/templer/core/tests/test_licenses.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import os import tempfile diff --git a/src/templer/core/tests/test_package_template.py b/src/templer/core/tests/test_package_template.py index beb9db6..cc512be 100644 --- a/src/templer/core/tests/test_package_template.py +++ b/src/templer/core/tests/test_package_template.py @@ -1,6 +1,9 @@ import os import tempfile -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import pkg_resources import shutil diff --git a/src/templer/core/tests/test_script.py b/src/templer/core/tests/test_script.py index 1b09296..c129486 100644 --- a/src/templer/core/tests/test_script.py +++ b/src/templer/core/tests/test_script.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- - -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import sys -import StringIO +from templer.core.compat import StringIO # from templer.core.control_script import checkdots # from templer.core.control_script import process_args diff --git a/src/templer/core/tests/test_templates.py b/src/templer/core/tests/test_templates.py index 2458b30..dc10bec 100644 --- a/src/templer/core/tests/test_templates.py +++ b/src/templer/core/tests/test_templates.py @@ -1,8 +1,12 @@ # -*- coding: utf-8 -*- +from __future__ import print_function __docformat__ = 'restructuredtext' -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import doctest import sys @@ -24,7 +28,7 @@ def rmdir(*args): def templer(cmd, runner=None, silent=False): if not silent: - print "templer %s" % cmd + print("templer %s" % cmd) from templer.core.control_script import run args = cmd.split() kwargs = {'exit': False} @@ -69,9 +73,9 @@ def ls(*args): # very predictable. Hide them. if filename.endswith('.egg'): continue - print filename + print(filename) else: - print 'No directory named %s' % dirname + print('No directory named %s' % dirname) def cd(*args): @@ -86,9 +90,9 @@ def config(filename): def cat(*args): filename = os.path.join(*args) if os.path.isfile(filename): - print open(filename).read() + print(open(filename).read()) else: - print 'No file named %s' % filename + print('No file named %s' % filename) def touch(*args, **kwargs): diff --git a/src/templer/core/tests/test_vars.py b/src/templer/core/tests/test_vars.py index acf5e80..2d12f0a 100644 --- a/src/templer/core/tests/test_vars.py +++ b/src/templer/core/tests/test_vars.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- -import unittest2 as unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import sys from templer.core.vars import var @@ -12,6 +15,7 @@ from templer.core.vars import IntVar from templer.core.vars import BoundedIntVar from templer.core.vars import ValidationException +from templer.core import compat class test_var(unittest.TestCase): @@ -131,7 +135,7 @@ def setUp(self): self.bivar = BoundedIntVar('name', 'description', min=3, max=10) self.defaultminvar = BoundedIntVar('name', 'description', max=10) self.defaultmaxvar = BoundedIntVar('name', 'description', min=3) - self.max = sys.maxint + self.max = compat.maxint self.min = -self.max - 1 def testValidation(self): diff --git a/src/templer/core/ui.py b/src/templer/core/ui.py index d09b39b..df583f9 100644 --- a/src/templer/core/ui.py +++ b/src/templer/core/ui.py @@ -76,9 +76,9 @@ def _get_templates(template_entry_points, klass): 'Local Commands'), 'help': getattr(template, 'help', "").strip(), 'entry': entry}) - except Exception, e: + except Exception as e: # We will not be stopped! - print 'Warning: could not load entry point %s (%s: %s)' % ( - entry.name, e.__class__.__name__, e) + print('Warning: could not load entry point %s (%s: %s)' % ( + entry.name, e.__class__.__name__, e)) return templates - \ No newline at end of file + diff --git a/src/templer/core/vars.py b/src/templer/core/vars.py index 1044c5d..15a76c4 100644 --- a/src/templer/core/vars.py +++ b/src/templer/core/vars.py @@ -1,5 +1,7 @@ +from __future__ import print_function import sys from templer.core.create import NoDefault +from templer.core import compat ########################################################################## @@ -82,18 +84,18 @@ def print_vars(cls, vars, indent=0): max_name = max([len(v.name) for v in vars]) for var in vars: if var.description: - print '%s%s%s %s' % ( + print('%s%s%s %s' % ( ' ' * indent, var.name, ' ' * (max_name - len(var.name)), - var.description) + var.description)) else: - print ' %s' % var.name + print(' %s' % var.name) if var.default is not NoDefault: - print ' default: %r' % var.default + print(' default: %r' % var.default) if var.should_echo is True: - print ' should_echo: %s' % var.should_echo - print + print(' should_echo: %s' % var.should_echo) + print() @property def _is_structural(self): @@ -107,7 +109,7 @@ class BooleanVar(var): def validate(self, value): #Get rid of bonus whitespace - if isinstance(value, basestring): + if isinstance(value, compat.string_types): value = value.strip().lower() #Map special cases to correct values. @@ -128,7 +130,7 @@ class StringVar(var): _default_widget = 'string' def validate(self, value): - if not isinstance(value, basestring): + if not isinstance(value, compat.string_types): raise ValidationException("Not a string value: %s" % value) value = value.strip() @@ -170,7 +172,7 @@ class OnOffVar(StringVar): def validate(self, value): #Get rid of bonus whitespace - if isinstance(value, basestring): + if isinstance(value, compat.string_types): value = value.strip().lower() #Map special cases to correct values. @@ -198,7 +200,7 @@ def validate(self, value): return value -MAXINT = sys.maxint +MAXINT = compat.maxint MININT = -MAXINT-1 @@ -222,7 +224,7 @@ def validate(self, value): # first validate that value is an integer try: val = super(BoundedIntVar, self).validate(value) - except ValidationException, e: + except ValidationException as e: raise e if not self.min <= val <= self.max: @@ -239,7 +241,7 @@ class DottedVar(var): def validate(self, value): msg = "Not a valid Python dotted name: %s ('%s' is not an identifier)" - if not isinstance(value, basestring): + if not isinstance(value, compat.string_types): raise ValidationException("Not a string value: %s" % value) value = value.strip() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..0fa1390 --- /dev/null +++ b/tox.ini @@ -0,0 +1,13 @@ +[tox] +envlist = py26,py27,py33 + +[testenv:py26] +deps = nose + coverage + unittest2 +commands = nosetests -s src/templer/core + +[testenv] +deps = nose + coverage +commands = nosetests -s src/templer/core