From 572d3d799133b9dcf1f39b318d9ef906104bd12b 2010-10-10 20:13:38 From: Fernando Perez Date: 2010-10-10 20:13:38 Subject: [PATCH] Merge branch 'takowl-ipy3-preparation' into trunk This branch cleans up our trunk to make a 2to3 run be as painless as possible, while keeping our code fully 2.6-compatible. Closes gh-159 (pull request). --- diff --git a/.gitignore b/.gitignore index f7f5358..01d9a61 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ docs/source/api/generated *.pyc build *.egg-info +*.py~ +*.bak diff --git a/IPython/__init__.py b/IPython/__init__.py index 2a0bc8d..0f7b866 100755 --- a/IPython/__init__.py +++ b/IPython/__init__.py @@ -47,7 +47,7 @@ from .testing import test # Release data __author__ = '' -for author, email in release.authors.values(): +for author, email in release.authors.itervalues(): __author__ += author + ' <' + email + '>\n' __license__ = release.license __version__ = release.version diff --git a/IPython/config/configurable.py b/IPython/config/configurable.py index 18cb050..ed8fc2a 100755 --- a/IPython/config/configurable.py +++ b/IPython/config/configurable.py @@ -112,7 +112,7 @@ class Configurable(HasTraits): # dynamically create the section with name self.__class__.__name__. if new._has_section(sname): my_config = new[sname] - for k, v in traits.items(): + for k, v in traits.iteritems(): # Don't allow traitlets with config=True to start with # uppercase. Otherwise, they are confused with Config # subsections. But, developers shouldn't have uppercase diff --git a/IPython/config/loader.py b/IPython/config/loader.py index df79679..33f7deb 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # coding: utf-8 """A simple configuration system. @@ -73,7 +74,7 @@ class Config(dict): def _merge(self, other): to_update = {} - for k, v in other.items(): + for k, v in other.iteritems(): if not self.has_key(k): to_update[k] = v else: # I have this key @@ -92,15 +93,17 @@ class Config(dict): else: return False - def has_key(self, key): + def __contains__(self, key): if self._is_section_key(key): return True else: - return dict.has_key(self, key) + return super(Config, self).__contains__(key) + # .has_key is deprecated for dictionaries. + has_key = __contains__ def _has_section(self, key): if self._is_section_key(key): - if dict.has_key(self, key): + if super(Config, self).__contains__(key): return True return False @@ -363,7 +366,7 @@ class ArgParseConfigLoader(CommandLineConfigLoader): def _convert_to_config(self): """self.parsed_data->self.config""" - for k, v in vars(self.parsed_data).items(): + for k, v in vars(self.parsed_data).iteritems(): exec_str = 'self.config.' + k + '= v' exec exec_str in locals(), globals() diff --git a/IPython/core/completerlib.py b/IPython/core/completerlib.py index 23ad50c..95f0e4b 100644 --- a/IPython/core/completerlib.py +++ b/IPython/core/completerlib.py @@ -336,7 +336,7 @@ def cd_completer(self, event): return [compress_user(relpath, tilde_expand, tilde_val)] # if no completions so far, try bookmarks - bks = self.db.get('bookmarks',{}).keys() + bks = self.db.get('bookmarks',{}).iterkeys() bkmatches = [s for s in bks if s.startswith(event.symbol)] if bkmatches: return bkmatches diff --git a/IPython/core/history.py b/IPython/core/history.py index 8be2c49..39ebd3c 100644 --- a/IPython/core/history.py +++ b/IPython/core/history.py @@ -260,7 +260,7 @@ class ShadowHist(object): def all(self): d = self.db.hdict('shadowhist') - items = [(i,s) for (s,i) in d.items()] + items = [(i,s) for (s,i) in d.iteritems()] items.sort() return items diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index bb857dc..d4b28c9 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -22,13 +22,12 @@ import __future__ import abc import atexit import codeop -import exceptions -import new import os import re import string import sys import tempfile +import types from contextlib import nested from IPython.config.configurable import Configurable @@ -102,7 +101,7 @@ def softspace(file, newvalue): def no_op(*a, **kw): pass -class SpaceInInput(exceptions.Exception): pass +class SpaceInInput(Exception): pass class Bunch: pass @@ -512,7 +511,7 @@ class InteractiveShell(Configurable, Magic): def restore_sys_module_state(self): """Restore the state of the sys module.""" try: - for k, v in self._orig_sys_module_state.items(): + for k, v in self._orig_sys_module_state.iteritems(): setattr(sys, k, v) except AttributeError: pass @@ -550,7 +549,7 @@ class InteractiveShell(Configurable, Magic): # accepts it. Probably at least check that the hook takes the number # of args it's supposed to. - f = new.instancemethod(hook,self,self.__class__) + f = types.MethodType(hook, self) # check if the hook is for strdispatcher first if str_key is not None: @@ -1249,7 +1248,7 @@ class InteractiveShell(Configurable, Magic): def init_shadow_hist(self): try: self.db = pickleshare.PickleShareDB(self.ipython_dir + "/db") - except exceptions.UnicodeDecodeError: + except UnicodeDecodeError: print "Your ipython_dir can't be decoded to unicode!" print "Please set HOME environment variable to something that" print r"only has ASCII characters, e.g. c:\home" @@ -1414,7 +1413,7 @@ class InteractiveShell(Configurable, Magic): if handler is None: handler = dummy_handler - self.CustomTB = new.instancemethod(handler,self,self.__class__) + self.CustomTB = types.MethodType(handler, self) self.custom_exceptions = exc_tuple def excepthook(self, etype, value, tb): @@ -1756,8 +1755,7 @@ class InteractiveShell(Configurable, Magic): The position argument (defaults to 0) is the index in the completers list where you want the completer to be inserted.""" - newcomp = new.instancemethod(completer,self.Completer, - self.Completer.__class__) + newcomp = types.MethodType(completer, self.Completer) self.Completer.matchers.insert(pos,newcomp) def set_readline_completer(self): @@ -1828,12 +1826,11 @@ class InteractiveShell(Configurable, Magic): print 'Magic function. Passed parameter is between < >:' print '<%s>' % parameter_s print 'The self object is:',self - + newcomp = types.MethodType(completer, self.Completer) self.define_magic('foo',foo_impl) """ - import new - im = new.instancemethod(func,self, self.__class__) + im = types.MethodType(func, self) old = getattr(self, "magic_" + magicname, None) setattr(self, "magic_" + magicname, im) return old diff --git a/IPython/core/prefilter.py b/IPython/core/prefilter.py index e427091..9b5d12a 100755 --- a/IPython/core/prefilter.py +++ b/IPython/core/prefilter.py @@ -237,7 +237,7 @@ class PrefilterManager(Configurable): This must be called after the priority of a transformer is changed. The :meth:`register_transformer` method calls this automatically. """ - self._transformers.sort(cmp=lambda x,y: x.priority-y.priority) + self._transformers.sort(key=lambda x: x.priority) @property def transformers(self): @@ -273,7 +273,7 @@ class PrefilterManager(Configurable): This must be called after the priority of a checker is changed. The :meth:`register_checker` method calls this automatically. """ - self._checkers.sort(cmp=lambda x,y: x.priority-y.priority) + self._checkers.sort(key=lambda x: x.priority) @property def checkers(self): diff --git a/IPython/core/tests/test_inputsplitter.py b/IPython/core/tests/test_inputsplitter.py index fd2dbfc..3e9bf07 100644 --- a/IPython/core/tests/test_inputsplitter.py +++ b/IPython/core/tests/test_inputsplitter.py @@ -28,7 +28,7 @@ from IPython.core import inputsplitter as isp # Note: at the bottom, there's a slightly more complete version of this that # can be useful during development of code here. -def mini_interactive_loop(raw_input): +def mini_interactive_loop(input_func): """Minimal example of the logic of an interactive interpreter loop. This serves as an example, and it is used by the test system with a fake @@ -43,7 +43,7 @@ def mini_interactive_loop(raw_input): while isp.push_accepts_more(): indent = ' '*isp.indent_spaces prompt = '>>> ' + indent - line = indent + raw_input(prompt) + line = indent + input_func(prompt) isp.push(line) # Here we just return input so we can use it in a test suite, but a real @@ -356,7 +356,7 @@ class InteractiveLoopTestCase(unittest.TestCase): # We can't check that the provided ns is identical to the test_ns, # because Python fills test_ns with extra keys (copyright, etc). But # we can check that the given dict is *contained* in test_ns - for k,v in ns.items(): + for k,v in ns.iteritems(): self.assertEqual(test_ns[k], v) def test_simple(self): diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 72f5fa1..d15af47 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -33,7 +33,7 @@ def test_rehashx(): # Practically ALL ipython development systems will have more than 10 aliases yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10) - for key, val in _ip.alias_manager.alias_table.items(): + for key, val in _ip.alias_manager.alias_table.iteritems(): # we must strip dots from alias names nt.assert_true('.' not in key) diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py index 61664e5..b40aaa5 100644 --- a/IPython/core/ultratb.py +++ b/IPython/core/ultratb.py @@ -712,14 +712,14 @@ class VerboseTB(TBTools): head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, exc, ' '*(75-len(str(etype))-len(pyver)), - pyver, string.rjust(date, 75) ) + pyver, date.rjust(75) ) head += "\nA problem occured executing Python code. Here is the sequence of function"\ "\ncalls leading up to the error, with the most recent (innermost) call last." else: # Simplified header head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, - string.rjust('Traceback (most recent call last)', - 75 - len(str(etype)) ) ) + 'Traceback (most recent call last)'.\ + rjust(75 - len(str(etype)) ) ) frames = [] # Flush cache before calling inspect. This helps alleviate some of the # problems with python 2.3's inspect.py. diff --git a/IPython/external/Itpl.py b/IPython/external/Itpl.py index 3423fe4..ea98172 100644 --- a/IPython/external/Itpl.py +++ b/IPython/external/Itpl.py @@ -78,7 +78,6 @@ __license__ = 'MIT' import string import sys from tokenize import tokenprog -from types import StringType class ItplError(ValueError): def __init__(self, text, pos): @@ -144,7 +143,7 @@ class Itpl: pos = 0 while 1: - dollar = string.find(format, "$", pos) + dollar = format.find("$", pos) if dollar < 0: break nextchar = format[dollar+1] diff --git a/IPython/external/configobj.py b/IPython/external/configobj.py index 9e64f18..303f10b 100644 --- a/IPython/external/configobj.py +++ b/IPython/external/configobj.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # configobj.py # A config file reader/writer that supports nested sections in config files. # Copyright (C) 2005-2008 Michael Foord, Nicola Larosa @@ -32,22 +33,7 @@ except ImportError: pass from types import StringTypes from warnings import warn -try: - from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE -except ImportError: - # Python 2.2 does not have these - # UTF-8 - BOM_UTF8 = '\xef\xbb\xbf' - # UTF-16, little endian - BOM_UTF16_LE = '\xff\xfe' - # UTF-16, big endian - BOM_UTF16_BE = '\xfe\xff' - if sys.byteorder == 'little': - # UTF-16, native endianness - BOM_UTF16 = BOM_UTF16_LE - else: - # UTF-16, native endianness - BOM_UTF16 = BOM_UTF16_BE +from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE # A dictionary mapping BOM to # the encoding to decode with, and what to set the @@ -101,21 +87,6 @@ wspace_plus = ' \r\t\n\v\t\'"' tsquot = '"""%s"""' tdquot = "'''%s'''" -try: - enumerate -except NameError: - def enumerate(obj): - """enumerate for Python 2.2.""" - i = -1 - for item in obj: - i += 1 - yield i, item - -try: - True, False -except NameError: - True, False = 1, 0 - __version__ = '4.5.2' @@ -814,7 +785,7 @@ class Section(dict): >>> c2 {'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}} """ - for key, val in indict.items(): + for key, val in indict.iteritems(): if (key in self and isinstance(self[key], dict) and isinstance(val, dict)): self[key].merge(val) @@ -1438,7 +1409,7 @@ class ConfigObj(Section): enc = BOM_LIST[self.encoding.lower()] if enc == 'utf_16': # For UTF16 we try big endian and little endian - for BOM, (encoding, final_encoding) in BOMS.items(): + for BOM, (encoding, final_encoding) in BOMS.iteritems(): if not final_encoding: # skip UTF8 continue @@ -1468,7 +1439,7 @@ class ConfigObj(Section): return self._decode(infile, self.encoding) # No encoding specified - so we need to check for UTF8/UTF16 - for BOM, (encoding, final_encoding) in BOMS.items(): + for BOM, (encoding, final_encoding) in BOMS.iteritems(): if not line.startswith(BOM): continue else: @@ -2481,7 +2452,7 @@ def flatten_errors(cfg, res, levels=None, results=None): if levels: levels.pop() return results - for (key, val) in res.items(): + for (key, val) in res.iteritems(): if val == True: continue if isinstance(cfg.get(key), dict): diff --git a/IPython/external/path.py b/IPython/external/path.py index 6b0f952..4abe32d 100644 --- a/IPython/external/path.py +++ b/IPython/external/path.py @@ -7,7 +7,7 @@ d = path('/home/guido/bin') for f in d.files('*.py'): f.chmod(0755) -This module requires Python 2.2 or later. +This module requires Python 2.5 or later. URL: http://www.jorendorff.com/articles/python/path @@ -30,9 +30,7 @@ Date: 9 Mar 2007 from __future__ import generators import sys, warnings, os, fnmatch, glob, shutil, codecs -# deprecated in python 2.6 -warnings.filterwarnings('ignore', r'.*md5.*') -import md5 +from hashlib import md5 __version__ = '2.2' __all__ = ['path'] @@ -49,38 +47,11 @@ else: except ImportError: pwd = None -# Pre-2.3 support. Are unicode filenames supported? -_base = str -_getcwd = os.getcwd -try: - if os.path.supports_unicode_filenames: - _base = unicode - _getcwd = os.getcwdu -except AttributeError: - pass - -# Pre-2.3 workaround for booleans -try: - True, False -except NameError: - True, False = 1, 0 - -# Pre-2.3 workaround for basestring. -try: - basestring -except NameError: - basestring = (str, unicode) - -# Universal newline support -_textmode = 'r' -if hasattr(file, 'newlines'): - _textmode = 'U' - class TreeWalkWarning(Warning): pass -class path(_base): +class path(unicode): """ Represents a filesystem path. For documentation on individual methods, consult their @@ -90,12 +61,12 @@ class path(_base): # --- Special Python methods. def __repr__(self): - return 'path(%s)' % _base.__repr__(self) + return 'path(%s)' % unicode.__repr__(self) # Adding a path and a string yields a path. def __add__(self, more): try: - resultStr = _base.__add__(self, more) + resultStr = unicode.__add__(self, more) except TypeError: #Python bug resultStr = NotImplemented if resultStr is NotImplemented: @@ -122,7 +93,7 @@ class path(_base): def getcwd(cls): """ Return the current working directory as a path object. """ - return cls(_getcwd()) + return cls(os.getcwdu()) getcwd = classmethod(getcwd) @@ -152,7 +123,7 @@ class path(_base): return base def _get_ext(self): - f, ext = os.path.splitext(_base(self)) + f, ext = os.path.splitext(unicode(self)) return ext def _get_drive(self): @@ -513,14 +484,14 @@ class path(_base): of all the files users have in their bin directories. """ cls = self.__class__ - return [cls(s) for s in glob.glob(_base(self / pattern))] + return [cls(s) for s in glob.glob(unicode(self / pattern))] # --- Reading or writing an entire file at once. def open(self, mode='r'): """ Open this file. Return a file object. """ - return file(self, mode) + return open(self, mode) def bytes(self): """ Open this file, read all bytes, return them as a string. """ @@ -563,7 +534,7 @@ class path(_base): """ if encoding is None: # 8-bit - f = self.open(_textmode) + f = self.open('U') try: return f.read() finally: @@ -690,7 +661,7 @@ class path(_base): This uses 'U' mode in Python 2.3 and later. """ if encoding is None and retain: - f = self.open(_textmode) + f = self.open('U') try: return f.readlines() finally: @@ -770,7 +741,7 @@ class path(_base): """ f = self.open('rb') try: - m = md5.new() + m = md5() while True: d = f.read(8192) if not d: diff --git a/IPython/external/pretty.py b/IPython/external/pretty.py index 6a7e855..6559fc4 100644 --- a/IPython/external/pretty.py +++ b/IPython/external/pretty.py @@ -101,7 +101,8 @@ Portions (c) 2009 by Robert Kern. :license: BSD License. """ -import __future__ +from __future__ import with_statement +from contextlib import contextmanager import sys import types import re @@ -138,12 +139,6 @@ def pprint(obj, verbose=False, max_width=79, newline='\n'): sys.stdout.write(newline) sys.stdout.flush() - -# add python2.5 context managers if we have the with statement feature -if hasattr(__future__, 'with_statement'): exec ''' -from __future__ import with_statement -from contextlib import contextmanager - class _PrettyPrinterBase(object): @contextmanager @@ -164,16 +159,6 @@ class _PrettyPrinterBase(object): yield finally: self.end_group(indent, close) -''' -else: - class _PrettyPrinterBase(object): - - def _unsupported(self, *a, **kw): - """unsupported operation""" - raise RuntimeError('not available in this python version') - group = indent = _unsupported - del _unsupported - class PrettyPrinter(_PrettyPrinterBase): """ diff --git a/IPython/external/pyparsing.py b/IPython/external/pyparsing.py index 91b106a..aa60fd8 100644 --- a/IPython/external/pyparsing.py +++ b/IPython/external/pyparsing.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # module pyparsing.py # # Copyright (c) 2003-2009 Paul T. McGuire @@ -400,7 +401,7 @@ class ParseResults(object): def values( self ): """Returns all named result values.""" - return [ v[-1][0] for v in self.__tokdict.values() ] + return [ v[-1][0] for v in self.__tokdict.itervalues() ] def __getattr__( self, name ): if name not in self.__slots__: @@ -422,7 +423,7 @@ class ParseResults(object): if other.__tokdict: offset = len(self.__toklist) addoffset = ( lambda a: (a<0 and offset) or (a+offset) ) - otheritems = other.__tokdict.items() + otheritems = other.__tokdict.iteritems() otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) for (k,vlist) in otheritems for v in vlist] for k,v in otherdictitems: @@ -488,7 +489,7 @@ class ParseResults(object): """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.""" nl = "\n" out = [] - namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() + namedItems = dict([(v[1],k) for (k,vlist) in self.__tokdict.iteritems() for v in vlist ] ) nextLevelIndent = indent + " " @@ -545,7 +546,7 @@ class ParseResults(object): return "".join(out) def __lookup(self,sub): - for k,vlist in self.__tokdict.items(): + for k,vlist in self.__tokdict.iteritems(): for v,loc in vlist: if sub is v: return k @@ -2563,7 +2564,7 @@ class Each(ParseExpression): tmp += ParseResults(r[k]) dups[k] = tmp finalResults += ParseResults(r) - for k,v in dups.items(): + for k,v in dups.iteritems(): finalResults[k] = v return loc, finalResults @@ -3442,7 +3443,7 @@ def withAttribute(*args,**attrDict): if args: attrs = args[:] else: - attrs = attrDict.items() + attrs = attrDict.iteritems() attrs = [(k,v) for k,v in attrs] def pa(s,l,tokens): for attrName,attrValue in attrs: diff --git a/IPython/kernel/launcher.py b/IPython/kernel/launcher.py index fbcc4e9..9b3f0e6 100644 --- a/IPython/kernel/launcher.py +++ b/IPython/kernel/launcher.py @@ -617,7 +617,7 @@ class WindowsHPCLauncher(BaseLauncher): # Twisted will raise DeprecationWarnings if we try to pass unicode to this output = yield getProcessOutput(str(self.job_cmd), [str(a) for a in args], - env=dict((str(k),str(v)) for k,v in os.environ.items()), + env=dict((str(k),str(v)) for k,v in os.environ.iteritems()), path=self.work_dir ) except: diff --git a/IPython/kernel/tests/test_pendingdeferred.py b/IPython/kernel/tests/test_pendingdeferred.py index e12b56b..4ee8a58 100644 --- a/IPython/kernel/tests/test_pendingdeferred.py +++ b/IPython/kernel/tests/test_pendingdeferred.py @@ -59,7 +59,7 @@ class PendingDeferredManagerTest(DeferredTestCase): did = self.pdm.save_pending_deferred(d) dDict[did] = d # Make sure they are begin saved - for k in dDict.keys(): + for k in dDict.iterkeys(): self.assert_(self.pdm.quick_has_id(k)) # Get the pending deferred (block=True), then callback with 'foo' and compare for did in dDict.keys()[0:5]: diff --git a/IPython/kernel/winhpcjob.py b/IPython/kernel/winhpcjob.py index b862bc8..c9219e2 100644 --- a/IPython/kernel/winhpcjob.py +++ b/IPython/kernel/winhpcjob.py @@ -212,7 +212,7 @@ class WinHPCTask(Configurable): def get_env_vars(self): env_vars = ET.Element('EnvironmentVariables') - for k, v in self.environment_variables.items(): + for k, v in self.environment_variables.iteritems(): variable = ET.SubElement(env_vars, "Variable") name = ET.SubElement(variable, "Name") name.text = k diff --git a/IPython/utils/importstring.py b/IPython/utils/importstring.py index 63f08e8..cbb6101 100644 --- a/IPython/utils/importstring.py +++ b/IPython/utils/importstring.py @@ -22,10 +22,15 @@ def import_item(name): """Import and return bar given the string foo.bar.""" package = '.'.join(name.split('.')[0:-1]) obj = name.split('.')[-1] - execString = 'from %s import %s' % (package, obj) - try: - exec execString - except SyntaxError: - raise ImportError("Invalid class specification: %s" % name) - exec 'temp = %s' % obj - return temp +# execString = 'from %s import %s' % (package, obj) +# try: +# exec execString +# except SyntaxError: +# raise ImportError("Invalid class specification: %s" % name) +# exec 'temp = %s' % obj +# return temp + if package: + module = __import__(package,fromlist=[obj]) + return module.__dict__[obj] + else: + return __import__(obj) diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index 4c7b3f8..39c8570 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -56,19 +56,7 @@ from types import ( InstanceType, ClassType, FunctionType, ListType, TupleType ) - -def import_item(name): - """Import and return bar given the string foo.bar.""" - package = '.'.join(name.split('.')[0:-1]) - obj = name.split('.')[-1] - execString = 'from %s import %s' % (package, obj) - try: - exec execString - except SyntaxError: - raise ImportError("Invalid class specification: %s" % name) - exec 'temp = %s' % obj - return temp - +from .importstring import import_item ClassTypes = (ClassType, type) diff --git a/IPython/utils/upgradedir.py b/IPython/utils/upgradedir.py index 1e7a88d..8ca7e51 100644 --- a/IPython/utils/upgradedir.py +++ b/IPython/utils/upgradedir.py @@ -11,7 +11,7 @@ try: except ImportError: from path import path -import md5, pickle +import hashlib, pickle def showdiff(old,new): import difflib @@ -59,23 +59,23 @@ def upgrade_dir(srcdir, tgtdir): pr("Creating %s" % str(tgt)) tgt.write_text(src.text()) - rpt[str(tgt)] = md5.new(tgt.text()).hexdigest() + rpt[str(tgt)] = hashlib.md5(tgt.text()).hexdigest() else: cont = tgt.text() sum = rpt.get(str(tgt), None) #print sum - if sum and md5.new(cont).hexdigest() == sum: + if sum and hashlib.md5(cont).hexdigest() == sum: pr("%s: Unedited, installing new version" % tgt) tgt.write_text(src.text()) - rpt[str(tgt)] = md5.new(tgt.text()).hexdigest() + rpt[str(tgt)] = hashlib.md5(tgt.text()).hexdigest() else: pr(' == Modified, skipping %s, diffs below == ' % tgt) - #rpt[str(tgt)] = md5.new(tgt.bytes()).hexdigest() + #rpt[str(tgt)] = hashlib.md5(tgt.bytes()).hexdigest() real = showdiff(tgt,src) pr('') # empty line if not real: pr("(Ok, it was identical, only upgrading checksum)") - rpt[str(tgt)] = md5.new(tgt.text()).hexdigest() + rpt[str(tgt)] = hashlib.md5(tgt.text()).hexdigest() else: modded.append(tgt)