[thunderbird-lightning/el5: 15/15] Update to 3.3; sync with EL5 TB
Orion Poplawski
orion at fedoraproject.org
Tue Oct 28 17:01:16 UTC 2014
commit 02ec8090ec5530171c1cb9e12af160034ee5e9ed
Merge: 7aa7389 049260e
Author: Orion Poplawski <orion at cora.nwra.com>
Date: Tue Oct 28 11:00:27 2014 -0600
Update to 3.3; sync with EL5 TB
.gitignore | 6 +
array_len.patch | 12 +
disable-webm.patch | 11 +
firefox-system-nss-3.16.2.patch | 12 +
mozilla-build-arm.patch | 12 +-
mozilla-python.patch | 3286 ++++++-
mozilla-python3.patch |17643 +++++++++++++++++++++++++++++++++
nullptr.patch | 11 +
pango-backport.patch | 60 +
rebase-dir.patch | 7577 ++++++++++++++
remove-ogg.patch | 449 +
rhbz-966424.patch | 23 +
sources | 6 +-
thunderbird-lightning-lightning.patch | 9 +
thunderbird-lightning.spec | 214 +-
thunderbird-mozconfig | 22 +-
thunderbird-objdir.patch | 13 +
xulrunner-10.0-secondary-ipc.patch | 36 -
xulrunner-24.0-jemalloc-ppc.patch | 12 +
xulrunner-24.0-s390-inlines.patch | 12 +
xulrunner-missing-pysqlite.patch | 22 -
21 files changed, 29210 insertions(+), 238 deletions(-)
---
diff --cc .gitignore
index 128fde8,b20d235..a84d5fe
--- a/.gitignore
+++ b/.gitignore
@@@ -43,8 -42,13 +43,14 @@@
/thunderbird-24.1.0.source.tar.bz2
/l10n-2.6.2.tar.xz
/lightning-2.6.2.source.tar.bz2
-/lighting-2.6.4.source.tar.bz2
-/l10n-2.6.4.tar.xz
/lightning-2.6.4.source.tar.bz2
+/l10n-2.6.4.tar.xz
+/setuptools-0.6c11-py2.4.egg
/lightning-2.6.5.source.tar.bz2
/l10n-2.6.5.tar.xz
+ /lightning-2.6.6.source.tar.bz2
+ /l10n-2.6.6.tar.xz
+ /lightning-3.3.source.tar.bz2
+ /l10n-3.3.tar.xz
+ /simplejson-2.1.1.tar.gz
++/virtualtools-1.7.2.zip
diff --cc mozilla-python3.patch
index 0000000,0000000..8530518
new file mode 100644
--- /dev/null
+++ b/mozilla-python3.patch
@@@ -1,0 -1,0 +1,17643 @@@
++diff -up comm-esr31/calendar/base/backend/icaljs/Makefile.in.python3 comm-esr31/calendar/base/backend/icaljs/Makefile.in
++--- comm-esr31/calendar/base/backend/icaljs/Makefile.in.python3 2014-07-17 18:04:04.000000000 -0600
+++++ comm-esr31/calendar/base/backend/icaljs/Makefile.in 2014-10-24 11:49:02.077039926 -0600
++@@ -36,7 +36,7 @@ libs:: $(BACKEND_MANIFESTS)
++ fname=`basename $$i`; \
++ dest=$(FINAL_TARGET)/components/$${fname}; \
++ $(RM) -f $$dest; \
++- $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i -o $$dest; \
+++ $(PYTHON) $(topsrcdir)/mozilla/python/mozbuild/mozbuild/action/preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i -o $$dest; \
++ done
++
++ # The install target must use SYSINSTALL, which is NSINSTALL in copy mode.
++diff -up comm-esr31/calendar/base/backend/libical/build/Makefile.in.python3 comm-esr31/calendar/base/backend/libical/build/Makefile.in
++--- comm-esr31/calendar/base/backend/libical/build/Makefile.in.python3 2014-07-17 18:04:04.000000000 -0600
+++++ comm-esr31/calendar/base/backend/libical/build/Makefile.in 2014-10-24 11:49:00.807045321 -0600
++@@ -44,5 +44,5 @@ libs:: $(BACKEND_MANIFESTS)
++ fname=`basename $$i`; \
++ dest=$(FINAL_TARGET)/components/$${fname}; \
++ $(RM) -f $$dest; \
++- $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i -o $$dest; \
+++ $(PYTHON) $(topsrcdir)/mozilla/python/mozbuild/mozbuild/action/preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i -o $$dest; \
++ done
++diff -up comm-esr31/client.mk.python3 comm-esr31/client.mk
++--- comm-esr31/client.mk.python3 2014-10-24 11:41:35.433880337 -0600
+++++ comm-esr31/client.mk 2014-10-24 11:41:35.437880320 -0600
++@@ -125,7 +125,8 @@ MOZCONFIG_OUT_FILTERED := $(filter-out $
++
++ # Automatically add -jN to make flags if not defined. N defaults to number of cores.
++ ifeq (,$(findstring -j,$(MOZ_MAKE_FLAGS)))
++- cores=$(shell $(PYTHON) -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+++ #cores=$(shell $(PYTHON) -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+++ cores=1
++ MOZ_MAKE_FLAGS += -j$(cores)
++ endif
++
++diff -up comm-esr31/config/config.mk.python3 comm-esr31/config/config.mk
++--- comm-esr31/config/config.mk.python3 2014-07-17 18:04:05.000000000 -0600
+++++ comm-esr31/config/config.mk 2014-10-24 11:41:35.438880316 -0600
++@@ -794,4 +794,5 @@ DEFINES += -DNO_NSPR_10_SUPPORT
++ #
++ # libs::
++ # $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
++-py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
+++py_action = $(PYTHON) $(topsrcdir)/mozilla/python/mozbuild/mozbuild/action/$(1).py $(2)
+++#py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
++diff -up comm-esr31/configure.in.python3 comm-esr31/configure.in
++--- comm-esr31/configure.in.python3 2014-07-17 18:04:05.000000000 -0600
+++++ comm-esr31/configure.in 2014-10-24 11:41:35.438880316 -0600
++@@ -7,6 +7,7 @@ dnl file, You can obtain one at http://m
++ dnl Process this file with autoconf to produce a configure script.
++ dnl ========================================================
++
+++dnl do some changes
++ AC_PREREQ(2.13)
++ AC_INIT(config/config.mk)
++ MOZILLA_SRCDIR=$topsrcdir/mozilla
++diff -up comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/__init__.py.python3 comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/__init__.py
++--- comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/__init__.py.python3 2014-07-17 18:05:06.000000000 -0600
+++++ comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/__init__.py 2014-10-24 11:41:35.438880316 -0600
++@@ -318,7 +318,10 @@ def parse_args(arguments, global_options
++ # a[0][1] = long name
++ names = []
++ for seq in (a, b):
++- names.append(seq[0][0][1:] if seq[0][0] else seq[0][1][2:])
+++ if seq[0][0]:
+++ names.append(seq[0][0][1:])
+++ else:
+++ names.append(seq[0][1][2:])
++ return cmp(*names)
++
++ global_options.sort(name_cmp)
++diff -up comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/rdf.py.python3 comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/rdf.py
++--- comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/rdf.py.python3 2014-07-17 18:05:06.000000000 -0600
+++++ comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/rdf.py 2014-10-24 11:41:35.438880316 -0600
++@@ -131,7 +131,7 @@ def gen_manifest(template_root_dir, targ
++ # XPIs remain packed by default, but package.json can override that. The
++ # RDF format accepts "true" as True, anything else as False. We expect
++ # booleans in the .json file, not strings.
++- manifest.set("em:unpack", "true" if target_cfg.get("unpack") else "false")
+++ manifest.set("em:unpack", ("false", "true")[target_cfg.get("unpack")])
++
++ for translator in target_cfg.get("translators", [ ]):
++ elem = dom.createElement("em:translator");
++diff -up comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py.python3 comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py
++--- comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py.python3 2014-07-17 18:05:06.000000000 -0600
+++++ comm-esr31/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py 2014-10-24 11:41:35.439880312 -0600
++@@ -293,8 +293,7 @@ class XulrunnerAppRunner(mozrunner.Runne
++
++ profile_class = XulrunnerAppProfile
++
++- # This is a default, and will be overridden in the instance if
++- # Firefox is used in XULRunner mode.
+++ # This is a default, and will be overridden in the instance if # Firefox is used in XULRunner mode.
++ names = ['xulrunner']
++
++ # Default location of XULRunner on OS X.
++diff -up comm-esr31/mozilla/b2g/simulator/build_xpi.py.python3 comm-esr31/mozilla/b2g/simulator/build_xpi.py
++--- comm-esr31/mozilla/b2g/simulator/build_xpi.py.python3 2014-07-17 18:05:06.000000000 -0600
+++++ comm-esr31/mozilla/b2g/simulator/build_xpi.py 2014-10-24 11:41:35.439880312 -0600
++@@ -40,9 +40,11 @@ class GaiaBuilder(object):
++ def override_prefs(self, srcfile):
++ # Note that each time we call `make profile` in gaia, a fresh new pref file is created
++ # cat srcfile >> profile/user.js
++- with open(os.path.join(self.gaia_path, "profile", "user.js"), "a") as userJs:
+++ userJs = open(os.path.join(self.gaia_path, "profile", "user.js"), "a")
+++ if 1:
++ userJs.write(open(srcfile).read())
++
+++ userJs.close()
++ def process_package_overload(src, dst, version, app_buildid):
++ ensureParentDir(dst)
++ # First replace numeric version like '1.3'
++@@ -57,10 +59,14 @@ def process_package_overload(src, dst, v
++ }
++ pp = Preprocessor(defines=defines)
++ pp.do_filter("substitution")
++- with open(dst, "w") as output:
++- with open(src, "r") as input:
+++ output = open(dst, "w")
+++ if 1:
+++ input = open(src, "r")
+++ if 1:
++ pp.processFile(input=input, output=output)
++
+++ input.close()
+++ output.close()
++ def add_dir_to_zip(zip, top, pathInZip, blacklist=()):
++ zf = ZipFile(zip, "a")
++ for dirpath, subdirs, files in os.walk(top):
++diff -up comm-esr31/mozilla/browser/locales/filter.py.python3 comm-esr31/mozilla/browser/locales/filter.py
++--- comm-esr31/mozilla/browser/locales/filter.py.python3 2014-07-17 18:05:09.000000000 -0600
+++++ comm-esr31/mozilla/browser/locales/filter.py 2014-10-24 11:41:35.439880312 -0600
++@@ -20,12 +20,12 @@ def test(mod, path, entity = None):
++ if mod == "extensions/spellcheck":
++ return "ignore"
++ # browser
++- return "ignore" if re.match(r"searchplugins\/.+\.xml", path) else "error"
+++ return ("error", "ignore")[re.match(r"searchplugins\/.+\.xml", path)]
++ if mod == "extensions/spellcheck":
++ # l10n ships en-US dictionary or something, do compare
++ return "error"
++ if path == "defines.inc":
++- return "ignore" if entity == "MOZ_LANGPACK_CONTRIBUTORS" else "error"
+++ return ("error", "ignore")[entity == "MOZ_LANGPACK_CONTRIBUTORS"]
++
++ if mod == "browser" and path == "chrome/browser-region/region.properties":
++ # only region.properties exceptions remain, compare all others
++diff -up comm-esr31/mozilla/build/appini_header.py.python3 comm-esr31/mozilla/build/appini_header.py
++--- comm-esr31/mozilla/build/appini_header.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/appini_header.py 2014-10-24 11:41:35.439880312 -0600
++@@ -25,8 +25,15 @@ def main(file):
++ flags.add('NS_XRE_ENABLE_CRASH_REPORTER')
++ except: pass
++ appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
++- appdata['flags'] = ' | '.join(flags) if flags else '0'
++- appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
+++ if flags:
+++ appdata['flags'] = ' | '.join(flags)
+++ else:
+++ appdata['flags'] = '0'
+++ if 'App:profile' in appdata:
+++ appdata['App:profile'] = '"%s"' % appdata['App:profile']
+++ else:
+++ appdata['App:profile'] = 'NULL'
+++ #appdata['flags'] = ' | '.join(flags)flags else '0' appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata = ('NULL', )[]
++ expected = ('App:vendor', 'App:name', 'App:version', 'App:buildid',
++ 'App:id', 'Gecko:minversion', 'Gecko:maxversion')
++ missing = [var for var in expected if var not in appdata]
++diff -up comm-esr31/mozilla/build/autoconf/config.status.m4.python3 comm-esr31/mozilla/build/autoconf/config.status.m4
++--- comm-esr31/mozilla/build/autoconf/config.status.m4.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/autoconf/config.status.m4 2014-10-24 11:41:35.439880312 -0600
++@@ -133,7 +133,8 @@ rm confdefs.pytmp confdefs.h
++ cat >> $CONFIG_STATUS <<\EOF
++ ] ]
++
++-substs = [(name[1:-1], value[1:-1] if isinstance(value, types.StringTypes) else value) for name, value in [
+++substs = []
+++mylist = [
++ EOF
++
++ dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
++@@ -149,7 +150,12 @@ for ac_subst_arg in $_subconfigure_ac_su
++ done
++
++ cat >> $CONFIG_STATUS <<\EOF
++-] ]
+++]
+++for name, value in mylist:
+++ if isinstance(value, types.StringTypes):
+++ substs.append( (name[1:-1], value[1:-1]) )
+++ else:
+++ substs.append( (name[1:-1], value) )
++
++ dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
++ non_global_defines = [
++diff -up comm-esr31/mozilla/build/automationutils.py.python3 comm-esr31/mozilla/build/automationutils.py
++--- comm-esr31/mozilla/build/automationutils.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/automationutils.py 2014-10-24 11:41:35.440880307 -0600
++@@ -3,7 +3,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++ import glob, logging, os, platform, shutil, subprocess, sys, tempfile, urllib2, zipfile
++ import base64
++ import re
++@@ -102,8 +102,7 @@ class ZipFileReader(object):
++
++ def _getnormalizedpath(self, path):
++ """
++- Gets a normalized path from 'path' (or the current working directory if
++- 'path' is None). Also asserts that the path exists.
+++ Gets a normalized path from 'path' (or the current working directory if 'path' is None). Also asserts that the path exists.
++ """
++ if path is None:
++ path = os.curdir
++@@ -123,9 +122,11 @@ class ZipFileReader(object):
++ path = os.path.split(filename)[0]
++ if not os.path.isdir(path):
++ os.makedirs(path)
++- with open(filename, "wb") as dest:
+++ dest = open(filename, "wb")
+++ if 1:
++ dest.write(self._zipfile.read(name))
++
+++ dest.close()
++ def namelist(self):
++ return self._zipfile.namelist()
++
++@@ -281,9 +282,11 @@ def dumpLeakLog(leakLogFile, filter = Fa
++ if not os.path.exists(leakLogFile):
++ return
++
++- with open(leakLogFile, "r") as leaks:
+++ leaks = open(leakLogFile, "r")
+++ if 1:
++ leakReport = leaks.read()
++
+++ leaks.close()
++ # Only |XPCOM_MEM_LEAK_LOG| reports can be actually filtered out.
++ # Only check whether an actual leak was reported.
++ if filter and not "0 TOTAL " in leakReport:
++@@ -312,7 +315,8 @@ def processSingleLeakFile(leakLogFileNam
++ totalBytesLeaked = None
++ leakAnalysis = []
++ leakedObjectNames = []
++- with open(leakLogFileName, "r") as leaks:
+++ leaks = open(leakLogFileName, "r")
+++ if 1:
++ for line in leaks:
++ if line.find("purposefully crash") > -1:
++ crashedOnPurpose = True
++@@ -340,6 +344,7 @@ def processSingleLeakFile(leakLogFileNam
++ leakedObjectNames.append(name)
++ leakAnalysis.append("TEST-INFO | leakcheck |%s leaked %d %s (%s bytes)"
++ % (processString, numLeaked, name, bytesLeaked))
+++ leaks.close()
++ log.info('\n'.join(leakAnalysis))
++
++ if totalBytesLeaked is None:
++@@ -451,7 +456,11 @@ def systemMemory():
++ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=None):
++ """populate OS environment variables for mochitest"""
++
++- env = os.environ.copy() if env is None else env
+++ env = None
+++ if env is None:
+++ env = os.environ.copy()
+++ else:
+++ env = env
++
++ assert os.path.isabs(xrePath)
++
++diff -up comm-esr31/mozilla/build/checksums.py.python3 comm-esr31/mozilla/build/checksums.py
++--- comm-esr31/mozilla/build/checksums.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/checksums.py 2014-10-24 11:41:35.440880307 -0600
++@@ -3,7 +3,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++
++ from optparse import OptionParser
++ import logging
++@@ -26,13 +26,15 @@ def digest_file(filename, digest, chunk_
++ if hashlib is not None:
++ logger.debug('Creating new %s object' % digest)
++ h = hashlib.new(digest)
++- with open(filename, 'rb') as f:
+++ f = open(filename, 'rb')
+++ if 1:
++ while True:
++ data = f.read(chunk_size)
++ if not data:
++ logger.debug('Finished reading in file')
++ break
++ h.update(data)
+++ f.close()
++ hash = h.hexdigest()
++ logger.debug('Hash for %s is %s' % (filename, hash))
++ return hash
++@@ -65,7 +67,8 @@ def process_files(files, output_filename
++ output_filename)
++ else:
++ logger.debug('Creating a new checksums file "%s"' % output_filename)
++- with open(output_filename, 'w+') as output:
+++ output = open(output_filename, 'w+')
+++ if 1:
++ for file in files:
++ if os.path.isdir(file):
++ logger.warn('%s is a directory, skipping' % file)
++@@ -85,6 +88,7 @@ def process_files(files, output_filename
++ os.path.getsize(file),
++ short_file)
++
+++ output.close()
++ def setup_logging(level=logging.DEBUG):
++ '''This function sets up the logging module using a speficiable logging
++ module logging level. The default log level is DEBUG.
++diff -up comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs.py.python3 comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs.py
++--- comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs.py 2014-10-24 11:41:35.440880307 -0600
++@@ -5,7 +5,7 @@
++
++ # originally from http://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py
++
++-from __future__ import unicode_literals
+++
++
++ import logging
++ import os
++diff -up comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs-wrapper.py.python3 comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs-wrapper.py
++--- comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs-wrapper.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/compare-mozconfig/compare-mozconfigs-wrapper.py 2014-10-24 11:41:35.440880307 -0600
++@@ -3,7 +3,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import subprocess
++ import sys
++diff -up comm-esr31/mozilla/build/gyp.mozbuild.python3 comm-esr31/mozilla/build/gyp.mozbuild
++--- comm-esr31/mozilla/build/gyp.mozbuild.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/gyp.mozbuild 2014-10-24 11:41:35.440880307 -0600
++@@ -8,10 +8,10 @@ gyp_vars = {
++ 'build_with_mozilla': 1,
++ 'build_with_chromium': 0,
++ 'use_official_google_api_keys': 0,
++- 'have_clock_monotonic': 1 if CONFIG['HAVE_CLOCK_MONOTONIC'] else 0,
++- 'have_ethtool_cmd_speed_hi': 1 if CONFIG['MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI'] else 0,
++- 'include_alsa_audio': 1 if CONFIG['MOZ_ALSA'] else 0,
++- 'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0,
+++ 'have_clock_monotonic': (0, 1)[CONFIG['HAVE_CLOCK_MONOTONIC'] == '1'],
+++ 'have_ethtool_cmd_speed_hi': (0, 1)[CONFIG['MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI'] == '1'],
+++ 'include_alsa_audio': (0, 1)[CONFIG['MOZ_ALSA'] == '1'],
+++ 'include_pulse_audio': (0, 1)[CONFIG['MOZ_PULSEAUDIO'] == '1'],
++ # basic stuff for everything
++ 'include_internal_video_render': 0,
++ 'clang_use_chrome_plugins': 0,
++@@ -26,7 +26,7 @@ gyp_vars = {
++ 'build_libvpx': 0,
++ 'build_libyuv': 0,
++ 'libyuv_dir': '/media/libyuv',
++- 'yuv_disable_avx2': 0 if CONFIG['HAVE_X86_AVX2'] else 1,
+++ 'yuv_disable_avx2': (1, 0)[CONFIG['HAVE_X86_AVX2'] == '1'],
++
++ # saves 4MB when webrtc_trace is off
++ 'enable_lazy_trace_alloc': 1,
++@@ -57,7 +57,7 @@ os = CONFIG['OS_TARGET']
++ if os == 'WINNT':
++ gyp_vars.update(
++ MSVS_VERSION=CONFIG['_MSVS_VERSION'],
++- MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_OS'] else 32,
+++ MSVS_OS_BITS=(32, 64)[CONFIG['HAVE_64BIT_OS'] == '1'],
++ )
++ elif os == 'Android':
++ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
++@@ -73,9 +73,9 @@ elif os == 'Android':
++
++ flavors = {
++ 'WINNT': 'win',
++- 'Android': 'linux' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' else 'android',
+++ 'Android': ('android', 'linux')[CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk'],
++ 'Linux': 'linux',
++- 'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
+++ 'Darwin': ('ios', 'mac')[CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa'],
++ 'SunOS': 'solaris',
++ 'GNU/kFreeBSD': 'freebsd',
++ 'DragonFly': 'dragonfly',
++diff -up comm-esr31/mozilla/build/link.py.python3 comm-esr31/mozilla/build/link.py
++--- comm-esr31/mozilla/build/link.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/link.py 2014-10-24 11:41:35.441880303 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++ import os, subprocess, sys, threading, time
++ from win32 import procmem
++
++@@ -25,9 +25,11 @@ def measure_vsize_threadfunc(proc, outpu
++ sys.stdout.flush()
++ idleTime = 0
++ print "TinderboxPrint: linker max vsize: %d" % maxvsize
++- with open(output_file, "w") as f:
+++ f = open(output_file, "w")
+++ if 1:
++ f.write("%d\n" % maxvsize)
++
+++ f.close()
++ def measure_link_vsize(output_file, args):
++ """
++ Execute |args|, and measure the maximum virtual memory usage of the process,
++diff -up comm-esr31/mozilla/build/mach_bootstrap.py.python3 comm-esr31/mozilla/build/mach_bootstrap.py
++--- comm-esr31/mozilla/build/mach_bootstrap.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/mach_bootstrap.py 2014-10-24 11:41:35.441880303 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import platform
++@@ -150,7 +154,7 @@ def bootstrap(topsrcdir, mozilla_dir=Non
++ if not os.path.exists(state_env_dir):
++ print('Creating global state directory from environment variable: %s'
++ % state_env_dir)
++- os.makedirs(state_env_dir, mode=0o770)
+++ os.makedirs(state_env_dir, mode=0770)
++ print('Please re-run mach.')
++ sys.exit(1)
++ state_dir = state_env_dir
++diff -up comm-esr31/mozilla/build/pgo/genpgocert.py.python3 comm-esr31/mozilla/build/pgo/genpgocert.py
++--- comm-esr31/mozilla/build/pgo/genpgocert.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pgo/genpgocert.py 2014-10-24 11:41:35.441880303 -0600
++@@ -52,7 +52,7 @@ def runUtil(util, args, inputdata = None
++ else:
++ env[pathvar] = app_path
++ proc = subprocess.Popen([util] + args, env=env,
++- stdin=subprocess.PIPE if inputdata else None)
+++ stdin=(None, subprocess.PIPE)[inputdata])
++ proc.communicate(inputdata)
++ return proc.returncode
++
++@@ -68,7 +68,8 @@ def createCertificateAuthority(build, sr
++
++ #TODO: mozfile.TemporaryDirectory
++ tempDbDir = tempfile.mkdtemp()
++- with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+++ pwfile, NamedTemporaryFile() = rndfile = NamedTemporaryFile().__enter__()
+++ if 1:
++ pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
++ pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
++
++@@ -92,6 +93,7 @@ def createCertificateAuthority(build, sr
++ if status:
++ return status
++
+++ rndfile.__exit__(0, 0, 0)
++ shutil.rmtree(tempDbDir)
++ return 0
++
++@@ -100,7 +102,8 @@ def createSSLServerCertificate(build, sr
++ certutil = build.get_binary_path(what="certutil")
++ pk12util = build.get_binary_path(what="pk12util")
++
++- with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+++ pwfile, NamedTemporaryFile() = rndfile = NamedTemporaryFile().__enter__()
+++ if 1:
++ pgoCAPath = os.path.join(srcDir, "pgoca.p12")
++
++ pwfile.write("\n")
++@@ -159,6 +162,7 @@ def createSSLServerCertificate(build, sr
++ if status:
++ return status
++
+++ rndfile.__exit__(0, 0, 0)
++ return 0
++
++ if len(sys.argv) == 1:
++diff -up comm-esr31/mozilla/build/pymake/pymake/builtins.py.python3 comm-esr31/mozilla/build/pymake/pymake/builtins.py
++--- comm-esr31/mozilla/build/pymake/pymake/builtins.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/pymake/builtins.py 2014-10-24 11:41:35.441880303 -0600
++@@ -109,7 +109,10 @@ def touch(args):
++ y += 1900
++ return y
++ if m.group(f) is None:
++- return localtime()[0] if f == 'Y' else 0
+++ if f == 'Y':
+++ return localtime()[0]
+++ else:
+++ return 0
++ return int(m.group(f))
++ time = [normalized_field(m, f) for f in ['Y', 'M', 'D', 'h', 'm', 's']] + [0, 0, -1]
++ time = mktime(time)
++diff -up comm-esr31/mozilla/build/pymake/pymake/data.py.python3 comm-esr31/mozilla/build/pymake/pymake/data.py
++--- comm-esr31/mozilla/build/pymake/pymake/data.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/pymake/data.py 2014-10-24 11:41:35.442880299 -0600
++@@ -53,7 +53,10 @@ def getmtime(path):
++ def stripdotslash(s):
++ if s.startswith('./'):
++ st = s[2:]
++- return st if st != '' else '.'
+++ if st != '':
+++ return st
+++ else:
+++ return '.'
++ return s
++
++ def stripdotslashes(sl):
++diff -up comm-esr31/mozilla/build/pymake/pymake/functions.py.python3 comm-esr31/mozilla/build/pymake/pymake/functions.py
++--- comm-esr31/mozilla/build/pymake/pymake/functions.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/pymake/functions.py 2014-10-24 11:41:35.442880299 -0600
++@@ -27,8 +27,10 @@ def emit_expansions(descend, *expansions
++ class Function(object):
++ """
++ An object that represents a function call. This class is always subclassed
++- with the following methods and attributes:
+++ the following methods and attributes.__enter__()
+++ if 1:
++
+++ the following methods and attributes.__exit__(0, 0, 0)
++ minargs = minimum # of arguments
++ maxargs = maximum # of arguments (0 means unlimited)
++
++diff -up comm-esr31/mozilla/build/pymake/pymake/process.py.python3 comm-esr31/mozilla/build/pymake/pymake/process.py
++--- comm-esr31/mozilla/build/pymake/pymake/process.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/pymake/process.py 2014-10-24 11:41:35.442880299 -0600
++@@ -382,7 +382,7 @@ class PythonJob(Job):
++ if self.module not in sys.modules:
++ try:
++ __import__(self.module)
++- except Exception as e:
+++ except Exception, e:
++ print >>sys.stderr, 'Error importing %s: %s' % (
++ self.module, e)
++ return -127
++@@ -396,7 +396,7 @@ class PythonJob(Job):
++ print >>sys.stderr, (
++ "Native command '%s %s' returned value '%s'" %
++ (self.module, self.method, rv))
++- return (rv if isinstance(rv, int) else 1)
+++ return ((1, rv)[isinstance(rv, int)])
++
++ except PythonException, e:
++ print >>sys.stderr, e
++diff -up comm-esr31/mozilla/build/pymake/tests/formattingtests.py.python3 comm-esr31/mozilla/build/pymake/tests/formattingtests.py
++--- comm-esr31/mozilla/build/pymake/tests/formattingtests.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/tests/formattingtests.py 2014-10-24 11:41:35.442880299 -0600
++@@ -253,9 +253,11 @@ class MakefileCorupusTest(TestBase):
++ continue
++
++ source = None
++- with open(makefile, 'rU') as fh:
+++ fh = open(makefile, 'rU')
+++ if 1:
++ source = fh.read()
++
+++ fh.close()
++ try:
++ yield (makefile, source, parsestring(source, makefile))
++ except SyntaxError:
++diff -up comm-esr31/mozilla/build/pymake/tests/pycmd.py.python3 comm-esr31/mozilla/build/pymake/tests/pycmd.py
++--- comm-esr31/mozilla/build/pymake/tests/pycmd.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/tests/pycmd.py 2014-10-24 11:41:35.443880295 -0600
++@@ -1,15 +1,20 @@
++ import os, sys, subprocess
++
++ def writetofile(args):
++- with open(args[0], 'w') as f:
+++ f = open(args[0], 'w')
+++ if 1:
++ f.write(' '.join(args[1:]))
++
+++ f.close()
++ def writeenvtofile(args):
++- with open(args[0], 'w') as f:
+++ f = open(args[0], 'w')
+++ if 1:
++ f.write(os.environ[args[1]])
++
+++ f.close()
++ def writesubprocessenvtofile(args):
++- with open(args[0], 'w') as f:
+++ f = open(args[0], 'w')
+++ if 1:
++ p = subprocess.Popen([sys.executable, "-c",
++ "import os; print os.environ['%s']" % args[1]],
++ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
++@@ -17,11 +22,12 @@ def writesubprocessenvtofile(args):
++ assert p.returncode == 0
++ f.write(stdout)
++
+++ f.close()
++ def convertasplode(arg):
++ try:
++ return int(arg)
++ except:
++- return (None if arg == "None" else arg)
+++ return ((arg, None)[arg == "None"])
++
++ def asplode(args):
++ arg0 = convertasplode(args[0])
++diff -up comm-esr31/mozilla/build/pymake/tests/subdir/pymod.py.python3 comm-esr31/mozilla/build/pymake/tests/subdir/pymod.py
++--- comm-esr31/mozilla/build/pymake/tests/subdir/pymod.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/pymake/tests/subdir/pymod.py 2014-10-24 11:41:35.443880295 -0600
++@@ -1,5 +1,8 @@
++ import testmodule
++
++ def writetofile(args):
++- with open(args[0], 'w') as f:
+++ f = open(args[0], 'w')
+++ if 1:
++ f.write(' '.join(args[1:]))
+++ f.close()
+++
++diff -up comm-esr31/mozilla/build/subconfigure.py.python3 comm-esr31/mozilla/build/subconfigure.py
++--- comm-esr31/mozilla/build/subconfigure.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/subconfigure.py 2014-10-24 11:41:35.443880295 -0600
++@@ -63,11 +63,13 @@ PRECIOUS_VARS = set([
++ def maybe_clear_cache():
++ comment = re.compile(r'^\s+#')
++ cache = {}
++- with open('config.cache') as f:
+++ f = open('config.cache')
+++ if 1:
++ for line in f.readlines():
++ if not comment.match(line) and '=' in line:
++ key, value = line.split('=', 1)
++ cache[key] = value
+++ f.close()
++ for precious in PRECIOUS_VARS:
++ entry = 'ac_cv_env_%s_value' % precious
++ if entry in cache and (not precious in os.environ or os.environ[precious] != cache[entry]):
++@@ -87,9 +89,10 @@ def dump(dump_file, shell):
++
++ # Scan the config.status output for information about configuration files
++ # it generates.
++- config_status_output = subprocess.check_output(
++- [shell, '-c', './config.status --help'],
++- stderr=subprocess.STDOUT).splitlines()
+++ config_status_output = subprocess.Popen([shell, '-c', './config.status --help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].splitlines()
+++ #config_status_output = subprocess.check_output(
+++ # [shell, '-c', './config.status --help'],
+++ # stderr=subprocess.STDOUT).splitlines()
++ state = None
++ for line in config_status_output:
++ if line.startswith('Configuration') and line.endswith(':'):
++@@ -101,10 +104,12 @@ def dump(dump_file, shell):
++ if os.path.isfile(f):
++ config_files.append(File(f))
++
++- with open(dump_file, 'wb') as f:
+++ f = open(dump_file, 'wb')
+++ if 1:
++ pickle.dump(config_files, f)
++
++
+++ f.close()
++ def adjust(dump_file, configure):
++ if not os.path.exists(dump_file):
++ return
++@@ -112,8 +117,10 @@ def adjust(dump_file, configure):
++ config_files = []
++
++ try:
++- with open(dump_file, 'rb') as f:
+++ f = open(dump_file, 'rb')
+++ if 1:
++ config_files = pickle.load(f)
+++ f.close()
++ except Exception:
++ pass
++
++@@ -134,4 +141,7 @@ if __name__ == '__main__':
++ if sys.argv[1] == 'dump':
++ dump(CONFIG_DUMP, sys.argv[2])
++ elif sys.argv[1] == 'adjust':
++- adjust(CONFIG_DUMP, sys.argv[2] if len(sys.argv) > 2 else None)
+++ if len(sys.argv) > 2:
+++ adjust(CONFIG_DUMP, sys.argv[2])
+++ else:
+++ adjust(CONFIG_DUMP, None)
++diff -up comm-esr31/mozilla/build/unix/add_phony_targets.py.python3 comm-esr31/mozilla/build/unix/add_phony_targets.py
++--- comm-esr31/mozilla/build/unix/add_phony_targets.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/unix/add_phony_targets.py 2014-10-24 11:41:35.443880295 -0600
++@@ -24,10 +24,12 @@ def add_phony_targets(path):
++ phony_targets = deps - targets
++ if not phony_targets:
++ return
++- with open(path, 'a') as f:
+++ f = open(path, 'a')
+++ if 1:
++ f.writelines('%s:\n' % d for d in phony_targets)
++
++
+++ f.close()
++ if __name__ == '__main__':
++ for f in sys.argv[1:]:
++ add_phony_targets(f)
++diff -up comm-esr31/mozilla/build/unix/build-clang/tooltool.py.python3 comm-esr31/mozilla/build/unix/build-clang/tooltool.py
++--- comm-esr31/mozilla/build/unix/build-clang/tooltool.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/unix/build-clang/tooltool.py 2014-10-24 11:41:35.443880295 -0600
++@@ -86,8 +86,10 @@ class FileRecord(object):
++
++ def validate_digest(self):
++ if self.present():
++- with open(self.filename, 'rb') as f:
+++ f = open(self.filename, 'rb')
+++ if 1:
++ return self.digest == digest_file(f, self.algorithm)
+++ f.close()
++ else:
++ log.debug("trying to validate digest on a missing file, %s', self.filename")
++ raise MissingFileException(filename=self.filename)
++@@ -265,9 +267,11 @@ def open_manifest(manifest_file):
++ """I know how to take a filename and load it into a Manifest object"""
++ if os.path.exists(manifest_file):
++ manifest = Manifest()
++- with open(manifest_file) as f:
+++ f = open(manifest_file)
+++ if 1:
++ manifest.load(f)
++ log.debug("loaded manifest from file '%s'" % manifest_file)
+++ f.close()
++ return manifest
++ else:
++ log.debug("tried to load absent file '%s' as manifest" % manifest_file)
++@@ -282,8 +286,7 @@ def list_manifest(manifest_file):
++ log.error("failed to load manifest file at '%s'" % manifest_file)
++ return False
++ for f in manifest.file_records:
++- print "%s\t%s\t%s" % ("P" if f.present() else "-",
++- "V" if f.present() and f.validate() else "-",
+++ print "%s\t%s\t%s" % (("P", "-")[f.present() else "-", "V" if f.present() and f.validate()],
++ f.filename)
++ return True
++
++@@ -345,8 +348,10 @@ def add_files(manifest_file, algorithm,
++ log.debug("added '%s' to manifest" % filename)
++ else:
++ all_files_added = False
++- with open(manifest_file, 'wb') as output:
+++ output = open(manifest_file, 'wb')
+++ if 1:
++ new_manifest.dump(output, fmt='json')
+++ output.close()
++ return all_files_added
++
++
++@@ -364,8 +369,10 @@ def fetch_file(base_url, file_record, ov
++ log.info("overwriting '%s' as requested" % file_record.filename)
++ else:
++ # All of the following is for a useful error message
++- with open(file_record.filename, 'rb') as f:
+++ f = open(file_record.filename, 'rb')
+++ if 1:
++ d = digest_file(f, file_record.algorithm)
+++ f.close()
++ log.error("digest mismatch between manifest(%s...) and local file(%s...)" % \
++ (file_record.digest[:8], d[:8]))
++ log.debug("full digests: manifest (%s) local file (%s)" % (file_record.digest, d))
++@@ -382,7 +389,8 @@ def fetch_file(base_url, file_record, ov
++ try:
++ f = urllib2.urlopen(url)
++ log.debug("opened %s for reading" % url)
++- with open(file_record.filename, 'wb') as out:
+++ out = open(file_record.filename, 'wb')
+++ if 1:
++ k = True
++ size = 0
++ while k:
++@@ -398,7 +406,8 @@ def fetch_file(base_url, file_record, ov
++ file_record.filename, file_record.size - size))
++ return False
++ log.info("fetched %s" % file_record.filename)
++- except (urllib2.URLError, urllib2.HTTPError) as e:
+++ out.close()
+++ except (urllib2.URLError, urllib2.HTTPError), e:
++ log.error("failed to fetch '%s': %s" % (file_record.filename, e),
++ exc_info=True)
++ return False
++@@ -544,7 +553,7 @@ def main():
++ try:
++ options[option] = cfg_file.get('general', option)
++ log.debug("read '%s' as '%s' from cfg_file" % (option, options[option]))
++- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
+++ except (ConfigParser.NoSectionError, ConfigParser.NoOptionError), e:
++ log.debug("%s in config file" % e, exc_info=True)
++
++ if not options.has_key('manifest'):
++@@ -552,7 +561,7 @@ def main():
++
++ if len(args) < 1:
++ parser.error('You must specify a command')
++- exit(0 if process_command(options, args) else 1)
+++ exit((1, 0)[process_command(options, args)])
++
++ if __name__ == "__main__":
++ main()
++diff -up comm-esr31/mozilla/build/util/hg.py.python3 comm-esr31/mozilla/build/util/hg.py
++--- comm-esr31/mozilla/build/util/hg.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/util/hg.py 2014-10-24 11:41:35.444880290 -0600
++@@ -140,8 +140,7 @@ def clone(repo, dest, branch=None, revis
++ If `revision` is set, only the specified revision and its ancestors will
++ be cloned.
++
++- If `update_dest` is set, then `dest` will be updated to `revision` if
++- set, otherwise to `branch`, otherwise to the head of default.
+++ If `update_dest` is set, then `dest` will be updated to `revision` if set, otherwise to `branch`, otherwise to the head of default.
++
++ If `mirrors` is set, will try and clone from the mirrors before
++ cloning from `repo`.
++@@ -242,8 +241,7 @@ def common_args(revision=None, branch=No
++ def pull(repo, dest, update_dest=True, mirrors=None, **kwargs):
++ """Pulls changes from hg repo and places it in `dest`.
++
++- If `update_dest` is set, then `dest` will be updated to `revision` if
++- set, otherwise to `branch`, otherwise to the head of default.
+++ If `update_dest` is set, then `dest` will be updated to `revision` if set, otherwise to `branch`, otherwise to the head of default.
++
++ If `mirrors` is set, will try and pull from the mirrors first before
++ `repo`."""
++@@ -262,8 +260,7 @@ def pull(repo, dest, update_dest=True, m
++ repo = _make_absolute(repo)
++ cmd = ['hg', 'pull']
++ # Don't pass -r to "hg pull", except when it's a valid HG revision.
++- # Pulling using tag names is dangerous: it uses the local .hgtags, so if
++- # the tag has moved on the remote side you won't pull the new revision the
+++ # Pulling using tag names is dangerous: it uses the local .hgtags, so if # the tag has moved on the remote side you won't pull the new revision the
++ # remote tag refers to.
++ pull_kwargs = kwargs.copy()
++ if 'revision' in pull_kwargs and \
++diff -up comm-esr31/mozilla/build/valgrind/mach_commands.py.python3 comm-esr31/mozilla/build/valgrind/mach_commands.py
++--- comm-esr31/mozilla/build/valgrind/mach_commands.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/valgrind/mach_commands.py 2014-10-24 11:41:35.444880290 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import re
++@@ -62,7 +66,8 @@ class MachCommands(MachCommandBase):
++ httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
++ httpd.start(block=False)
++
++- with TemporaryDirectory() as profilePath:
+++ profilePath = TemporaryDirectory().__enter__()
+++ if 1:
++ #TODO: refactor this into mozprofile
++ prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles', 'prefs_general.js')
++ prefs = {}
++@@ -156,3 +161,5 @@ class MachCommands(MachCommandBase):
++ httpd.stop()
++
++ return status
+++ profilePath.__exit__(0, 0, 0)
+++
++diff -up comm-esr31/mozilla/build/valgrind/output_handler.py.python3 comm-esr31/mozilla/build/valgrind/output_handler.py
++--- comm-esr31/mozilla/build/valgrind/output_handler.py.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/valgrind/output_handler.py 2014-10-24 11:41:35.444880290 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import re
++
++@@ -28,8 +32,7 @@ class OutputHandler(object):
++ It buffers these lines from which text is extracted so that the
++ TEST-UNEXPECTED-FAIL message can be printed before the full error.
++
++- Parsing the Valgrind output isn't ideal, and it may break in the future if
++- Valgrind changes the format of the messages, or introduces new error kinds.
+++ Parsing the Valgrind output isn't ideal, and it may break in the future if Valgrind changes the format of the messages, or introduces new error kinds.
++ To protect against this, we also count how many lines containing
++ "<insert_a_suppression_name_here>" are seen. Thanks to the use of
++ --gen-suppressions=yes, exactly one of these lines is present per error. If
++diff -up comm-esr31/mozilla/build/virtualenv_packages.txt.python3 comm-esr31/mozilla/build/virtualenv_packages.txt
++--- comm-esr31/mozilla/build/virtualenv_packages.txt.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/build/virtualenv_packages.txt 2014-10-24 11:41:35.444880290 -0600
++@@ -22,3 +22,5 @@ copy:build/buildconfig.py
++ packages.txt:testing/mozbase/packages.txt
++ objdir:build
++ gyp.pth:media/webrtc/trunk/tools/gyp/pylib
+++rebase.pth:rebase
+++action.pth:python/mozbuild/action
++diff -up comm-esr31/mozilla/client.mk.python3 comm-esr31/mozilla/client.mk
++--- comm-esr31/mozilla/client.mk.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/client.mk 2014-10-24 11:41:35.444880290 -0600
++@@ -137,7 +137,8 @@ endif
++
++ # Automatically add -jN to make flags if not defined. N defaults to number of cores.
++ ifeq (,$(findstring -j,$(MOZ_MAKE_FLAGS)))
++- cores=$(shell $(PYTHON) -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+++ #cores=$(shell $(PYTHON) -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+++ cores=1 # $(shell $(PYTHON) -c 'import multiprocessing; print(multiprocessing.cpu_count())')
++ MOZ_MAKE_FLAGS += -j$(cores)
++ endif
++
++diff -up comm-esr31/mozilla/config/configobj.py.python3 comm-esr31/mozilla/config/configobj.py
++--- comm-esr31/mozilla/config/configobj.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/configobj.py 2014-10-24 11:41:35.445880286 -0600
++@@ -542,8 +542,7 @@ class Section(dict):
++ (We have to special case 'Section' instances - which are also dicts)
++
++ Keys must be strings.
++- Values need only be strings (or lists of strings) if
++- ``main.stringify`` is set.
+++ Values need only be strings (or lists of strings) if ``main.stringify`` is set.
++
++ `unrepr`` must be set when setting a value to a dictionary, without
++ creating a new sub-section.
++diff -up comm-esr31/mozilla/config/expandlibs_exec.py.python3 comm-esr31/mozilla/config/expandlibs_exec.py
++--- comm-esr31/mozilla/config/expandlibs_exec.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/expandlibs_exec.py 2014-10-24 11:41:35.445880286 -0600
++@@ -20,7 +20,7 @@ With the --symbol-order argument, follow
++ relevant linker options to change the order in which the linker puts the
++ symbols appear in the resulting binary. Only works for ELF targets.
++ '''
++-from __future__ import with_statement
+++
++ import sys
++ import os
++ from expandlibs import (
++@@ -186,8 +186,10 @@ class ExpandArgsMore(ExpandArgs):
++ def orderSymbols(self, order):
++ '''Given a file containing a list of symbols, adds the appropriate
++ argument to make the linker put the symbols in that order.'''
++- with open(order) as file:
+++ file = open(order)
+++ if 1:
++ sections = self._getOrderedSections([l.strip() for l in file.readlines() if l.strip()])
+++ file.close()
++ split_sections = {}
++ linked_sections = [s[0] for s in SECTION_INSERT_BEFORE]
++ for s in sections:
++@@ -292,8 +294,10 @@ def print_command(out, args):
++ print >>out, "Executing: " + " ".join(args)
++ for tmp in [f for f in args.tmp if os.path.isfile(f)]:
++ print >>out, tmp + ":"
++- with open(tmp) as file:
+++ file = open(tmp)
+++ if 1:
++ print >>out, "".join([" " + l for l in file.readlines()])
+++ file.close()
++ out.flush()
++
++ def main():
++@@ -322,7 +326,8 @@ def main():
++ deps.pop(0)
++ # Remove command
++ deps.pop(0)
++- with ExpandArgsMore(args) as args:
+++ args = ExpandArgsMore(args).__enter__()
+++ if 1:
++ if options.extract:
++ args.extract()
++ if options.symbol_order:
++@@ -344,6 +349,7 @@ def main():
++ sys.stderr.flush()
++ if proc.returncode:
++ exit(proc.returncode)
+++ args.__exit__(0, 0, 0)
++ if not options.depend:
++ return
++ ensureParentDir(options.depend)
++@@ -355,8 +361,10 @@ def main():
++ if len(deps) != len(no_dynamic_lib):
++ mk.create_rule(['%s_order_only' % options.target]).add_dependencies(dep for dep in deps if isDynamicLib(dep))
++
++- with open(options.depend, 'w') as depfile:
+++ depfile = open(options.depend, 'w')
+++ if 1:
++ mk.dump(depfile, removal_guard=True)
++
+++ depfile.close()
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/config/expandlibs_gen.py.python3 comm-esr31/mozilla/config/expandlibs_gen.py
++--- comm-esr31/mozilla/config/expandlibs_gen.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/expandlibs_gen.py 2014-10-24 11:41:35.445880286 -0600
++@@ -5,7 +5,7 @@
++ '''Given a list of object files and library names, prints a library
++ descriptor to standard output'''
++
++-from __future__ import with_statement
+++
++ import sys
++ import os
++ import expandlibs_config as conf
++@@ -39,12 +39,17 @@ if __name__ == '__main__':
++ raise Exception("Missing option: -o")
++
++ ensureParentDir(options.output)
++- with open(options.output, 'w') as outfile:
+++ outfile = open(options.output, 'w')
+++ if 1:
++ print >>outfile, generate(args)
+++ outfile.close()
++ if options.depend:
++ ensureParentDir(options.depend)
++- with open(options.depend, 'w') as depfile:
+++ depfile = open(options.depend, 'w')
+++ if 1:
++ deps = ExpandLibsDeps(args)
++ depfile.write("%s : %s\n" % (options.output, ' '.join(deps)))
++ for dep in deps:
++ depfile.write("%s :\n" % dep)
+++ depfile.close()
+++
++diff -up comm-esr31/mozilla/config/expandlibs.py.python3 comm-esr31/mozilla/config/expandlibs.py
++--- comm-esr31/mozilla/config/expandlibs.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/expandlibs.py 2014-10-24 11:41:35.446880282 -0600
++@@ -26,9 +26,10 @@ ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} follo
++ descriptor contains. And for each of these LIBS, also apply the same
++ rules.
++ '''
++-from __future__ import with_statement
+++
++ import sys, os, errno
++ import expandlibs_config as conf
+++from rhrebase import all, any
++
++ def ensureParentDir(file):
++ '''Ensures the directory parent to the given file exists'''
++@@ -125,8 +126,10 @@ class ExpandArgs(list):
++ def _expand_desc(self, arg):
++ '''Internal function taking care of lib descriptor expansion only'''
++ if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
++- with open(arg + conf.LIBS_DESC_SUFFIX, 'r') as f:
+++ f = open(arg + conf.LIBS_DESC_SUFFIX, 'r')
+++ if 1:
++ desc = LibDescriptor(f.readlines())
+++ f.close()
++ objs = [relativize(o) for o in desc['OBJS']]
++ for lib in desc['LIBS']:
++ objs += self._expand(lib)
++diff -up comm-esr31/mozilla/config/Makefile.in.python3 comm-esr31/mozilla/config/Makefile.in
++--- comm-esr31/mozilla/config/Makefile.in.python3 2014-07-17 18:05:10.000000000 -0600
+++++ comm-esr31/mozilla/config/Makefile.in 2014-10-24 11:41:35.446880282 -0600
++@@ -66,7 +66,7 @@ export-preqs = \
++ $(NULL)
++
++ export:: $(export-preqs)
++- $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) \
+++ $(PYTHON) $(topsrcdir)/python/mozbuild/mozbuild/action/preprocessor.py $(DEFINES) $(ACDEFINES) \
++ -DMOZ_TREE_CAIRO=$(MOZ_TREE_CAIRO) \
++ -DMOZ_TREE_PIXMAN=$(MOZ_TREE_PIXMAN) \
++ -DMOZ_NATIVE_HUNSPELL=$(MOZ_NATIVE_HUNSPELL) \
++diff -up comm-esr31/mozilla/config/makefiles/functions.mk.python3 comm-esr31/mozilla/config/makefiles/functions.mk
++--- comm-esr31/mozilla/config/makefiles/functions.mk.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/makefiles/functions.mk 2014-10-24 11:41:35.446880282 -0600
++@@ -30,5 +30,6 @@ core_winabspath = $(error core_winabspat
++ ifdef .PYMAKE
++ py_action = %mozbuild.action.$(1) main $(2)
++ else
++-py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
+++#py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
+++py_action = $(PYTHON) $(topsrcdir)/python/mozbuild/mozbuild/action/$(1).py $(2)
++ endif
++diff -up comm-esr31/mozilla/config/make-stl-wrappers.py.python3 comm-esr31/mozilla/config/make-stl-wrappers.py
++--- comm-esr31/mozilla/config/make-stl-wrappers.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/make-stl-wrappers.py 2014-10-24 11:41:35.446880282 -0600
++@@ -1,10 +1,13 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import print_function
++ import os, re, string, sys
++ from mozbuild.util import FileAvoidWrite
++
+++
+++def print24(msg, file=sys.stdout, end="\n"):
+++ file.write(msg + end)
+++
++ def find_in_path(file, searchpath):
++ for dir in searchpath.split(os.pathsep):
++ f = os.path.join(dir, file)
++@@ -33,22 +36,26 @@ def main(outdir, compiler, template_file
++ path_to_new = header_path('new', compiler)
++
++ for header in open(header_list_file, 'r'):
+++ #print "NEW HEADER" + header
++ header = header.rstrip()
++ if 0 == len(header) or is_comment(header):
++ continue
++
++ path = header_path(header, compiler)
++- with FileAvoidWrite(os.path.join(outdir, header)) as f:
+++ f = FileAvoidWrite(os.path.join(outdir, header)).__enter__()
+++ if 1:
++ f.write(string.Template(template).substitute(HEADER=header,
++ HEADER_PATH=path,
++ NEW_HEADER_PATH=path_to_new))
+++ #f.__exit(0, 0, 0)
+++ f.close()
++
++
++ if __name__ == '__main__':
++ if 5 != len(sys.argv):
++- print("""Usage:
++- python {0} OUT_DIR ('msvc'|'gcc') TEMPLATE_FILE HEADER_LIST_FILE
++-""".format(sys.argv[0]), file=sys.stderr)
+++ print24("""Usage:
+++ python %s OUT_DIR ('msvc'|'gcc') TEMPLATE_FILE HEADER_LIST_FILE
+++""" % (sys.argv[0]), file=sys.stderr)
++ sys.exit(1)
++
++ main(*sys.argv[1:])
++diff -up comm-esr31/mozilla/config/mozunit.py.python3 comm-esr31/mozilla/config/mozunit.py
++--- comm-esr31/mozilla/config/mozunit.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/mozunit.py 2014-10-24 11:41:35.446880282 -0600
++@@ -93,18 +93,22 @@ class MockedOpen(object):
++ Context manager diverting the open builtin such that opening files
++ can open "virtual" file instances given when creating a MockedOpen.
++
++- with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
+++ MockedOpen({'foo': 'foo', 'bar': 'bar'}).__enter__()
+++ if 1:
++ f = open('foo', 'r')
++
+++ MockedOpen({'foo': 'foo', 'bar': 'bar'}).__exit__(0, 0, 0)
++ will thus open the virtual file instance for the file 'foo' to f.
++
++ MockedOpen also masks writes, so that creating or replacing files
++ doesn't touch the file system, while subsequently opening the file
++ will return the recorded content.
++
++- with MockedOpen():
+++ MockedOpen().__enter__()
+++ if 1:
++ f = open('foo', 'w')
++ f.write('foo')
+++ MockedOpen().__exit__(0, 0, 0)
++ self.assertRaises(Exception,f.open('foo', 'r'))
++ '''
++ def __init__(self, files = {}):
++diff -up comm-esr31/mozilla/config/nsinstall.py.python3 comm-esr31/mozilla/config/nsinstall.py
++--- comm-esr31/mozilla/config/nsinstall.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/nsinstall.py 2014-10-24 11:41:35.447880278 -0600
++@@ -9,7 +9,6 @@
++ # a full build environment set up.
++ # The basic limitation is, it doesn't even try to link and ignores
++ # all related options.
++-from __future__ import print_function
++ from optparse import OptionParser
++ import os
++ import os.path
++@@ -17,6 +16,9 @@ import sys
++ import shutil
++ import stat
++
+++def print24(msg, file=sys.stdout, end="\n"):
+++ file.write(msg + end)
+++
++ def _nsinstall_internal(argv):
++ usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
++ p = OptionParser(usage=usage)
++@@ -65,7 +67,7 @@ def _nsinstall_internal(argv):
++ dir = os.path.abspath(dir)
++ if os.path.exists(dir):
++ if not os.path.isdir(dir):
++- print('nsinstall: {0} is not a directory'.format(dir), file=sys.stderr)
+++ print24('nsinstall: %s is not a directory' % (dir), file=sys.stderr)
++ return 1
++ if mode:
++ os.chmod(dir, mode)
++@@ -76,7 +78,7 @@ def _nsinstall_internal(argv):
++ os.makedirs(dir, mode)
++ else:
++ os.makedirs(dir)
++- except Exception as e:
+++ except Exception, e:
++ # We might have hit EEXIST due to a race condition (see bug 463411) -- try again once
++ if try_again:
++ return maybe_create_dir(dir, mode, False)
++diff -up comm-esr31/mozilla/config/rebuild_check.py.python3 comm-esr31/mozilla/config/rebuild_check.py
++--- comm-esr31/mozilla/config/rebuild_check.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/rebuild_check.py 2014-10-24 11:41:35.447880278 -0600
++@@ -8,7 +8,7 @@ import errno
++ def mtime(path):
++ try:
++ return os.stat(path).st_mtime
++- except OSError as e:
+++ except OSError, e:
++ if e.errno == errno.ENOENT:
++ return -1
++ raise
++diff -up comm-esr31/mozilla/config/tests/unit-expandlibs.py.python3 comm-esr31/mozilla/config/tests/unit-expandlibs.py
++--- comm-esr31/mozilla/config/tests/unit-expandlibs.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/tests/unit-expandlibs.py 2014-10-24 11:41:35.447880278 -0600
++@@ -161,11 +161,15 @@ class TestExpandInit(TestCaseWithTmpDir)
++ self.libx_files = [self.tmpfile('libx', Obj(f)) for f in ['g', 'h', 'i']]
++ self.liby_files = [self.tmpfile('liby', Obj(f)) for f in ['j', 'k', 'l']] + [self.tmpfile('liby', Lib('z'))]
++ self.touch(self.libx_files + self.liby_files)
++- with open(self.tmpfile('libx', Lib('x') + config.LIBS_DESC_SUFFIX), 'w') as f:
+++ f = open(self.tmpfile('libx', Lib('x') + config.LIBS_DESC_SUFFIX), 'w')
+++ if 1:
++ f.write(str(generate(self.libx_files)))
++- with open(self.tmpfile('liby', Lib('y') + config.LIBS_DESC_SUFFIX), 'w') as f:
+++ f.close()
+++ f = open(self.tmpfile('liby', Lib('y') + config.LIBS_DESC_SUFFIX), 'w')
+++ if 1:
++ f.write(str(generate(self.liby_files + [self.tmpfile('libx', Lib('x'))])))
++
+++ f.close()
++ # Create various objects and libraries
++ self.arg_files = [self.tmpfile(f) for f in [Lib('a'), Obj('b'), Obj('c'), Lib('d'), Obj('e')]]
++ # We always give library names (LIB_PREFIX/SUFFIX), even for
++@@ -218,7 +222,8 @@ class TestExpandArgsMore(TestExpandInit)
++ def test_makelist(self):
++ '''Test grouping object files in lists'''
++ # ExpandArgsMore does the same as ExpandArgs
++- with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
+++ args = ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]).__enter__()
+++ if 1:
++ self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
++
++ # But also has an extra method replacing object files with a list
++@@ -233,16 +238,21 @@ class TestExpandArgsMore(TestExpandInit)
++ self.assertNotEqual(args[3][0], '@')
++ filename = args[3]
++ content = ['INPUT("{0}")'.format(relativize(f)) for f in objs]
++- with open(filename, 'r') as f:
+++ f = open(filename, 'r')
+++ if 1:
++ self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
+++ f.close()
++ elif config.EXPAND_LIBS_LIST_STYLE == "list":
++ self.assertEqual(args[3][0], '@')
++ filename = args[3][1:]
++ content = objs
++- with open(filename, 'r') as f:
+++ f = open(filename, 'r')
+++ if 1:
++ self.assertRelEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
++
+++ f.close()
++ tmp = args.tmp
+++ args.__exit__(0, 0, 0)
++ # Check that all temporary files are properly removed
++ self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
++
++@@ -294,7 +304,8 @@ class TestExpandArgsMore(TestExpandInit)
++
++ # ExpandArgsMore does the same as ExpandArgs
++ self.touch([self.tmpfile('liby', Lib('y'))])
++- with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
+++ args = ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]).__enter__()
+++ if 1:
++ self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])
++
++ # ExpandArgsMore also has an extra method extracting static libraries
++@@ -314,6 +325,7 @@ class TestExpandArgsMore(TestExpandInit)
++ self.assertRelEqual(args, ['foo', '-bar'] + extracted_args)
++
++ tmp = args.tmp
+++ args.__exit__(0, 0, 0)
++ # Check that all temporary files are properly removed
++ self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
++
++diff -up comm-esr31/mozilla/config/tests/unit-mozunit.py.python3 comm-esr31/mozilla/config/tests/unit-mozunit.py
++--- comm-esr31/mozilla/config/tests/unit-mozunit.py.python3 2014-07-17 18:05:11.000000000 -0600
+++++ comm-esr31/mozilla/config/tests/unit-mozunit.py 2014-10-24 11:41:35.447880278 -0600
++@@ -12,9 +12,11 @@ class TestMozUnit(unittest.TestCase):
++ def test_mocked_open(self):
++ # Create a temporary file on the file system.
++ (fd, path) = mkstemp()
++- with os.fdopen(fd, 'w') as file:
+++ file = os.fdopen(fd, 'w')
+++ if 1:
++ file.write('foobar');
++
+++ file.close()
++ self.assertFalse(os.path.exists('file1'))
++ self.assertFalse(os.path.exists('file2'))
++
++@@ -29,8 +31,10 @@ class TestMozUnit(unittest.TestCase):
++ self.assertEqual(open('file2', 'r').read(), 'content2')
++
++ # Check that overwriting these files alters their content.
++- with open('file1', 'w') as file:
+++ file = open('file1', 'w')
+++ if 1:
++ file.write('foo')
+++ file.close()
++ self.assertTrue(os.path.exists('file1'))
++ self.assertEqual(open('file1', 'r').read(), 'foo')
++
++@@ -42,8 +46,10 @@ class TestMozUnit(unittest.TestCase):
++ self.assertEqual(open('file2', 'r').read(), 'bar')
++
++ # Check that appending to a file does append
++- with open('file1', 'a') as file:
+++ file = open('file1', 'a')
+++ if 1:
++ file.write('bar')
+++ file.close()
++ self.assertEqual(open('file1', 'r').read(), 'foobar')
++
++ self.assertFalse(os.path.exists('file3'))
++@@ -53,8 +59,10 @@ class TestMozUnit(unittest.TestCase):
++ self.assertFalse(os.path.exists('file3'))
++
++ # Check that writing a new file does create the file.
++- with open('file3', 'w') as file:
+++ file = open('file3', 'w')
+++ if 1:
++ file.write('baz')
+++ file.close()
++ self.assertEqual(open('file3', 'r').read(), 'baz')
++ self.assertTrue(os.path.exists('file3'))
++
++@@ -63,17 +71,23 @@ class TestMozUnit(unittest.TestCase):
++
++ # Check that overwriting a file existing on the file system
++ # does modify its content.
++- with open(path, 'w') as file:
+++ file = open(path, 'w')
+++ if 1:
++ file.write('bazqux')
+++ file.close()
++ self.assertEqual(open(path, 'r').read(), 'bazqux')
++
++- with MockedOpen():
+++ MockedOpen().__enter__()
+++ if 1:
++ # Check that appending to a file existing on the file system
++ # does modify its content.
++- with open(path, 'a') as file:
+++ file = open(path, 'a')
+++ if 1:
++ file.write('bazqux')
+++ file.close()
++ self.assertEqual(open(path, 'r').read(), 'foobarbazqux')
++
+++ MockedOpen().__exit__(0, 0, 0)
++ # Check that the file was not actually modified on the file system.
++ self.assertEqual(open(path, 'r').read(), 'foobar')
++ os.remove(path)
++diff -up comm-esr31/mozilla/content/canvas/test/webgl-conformance/writemanifest.py.python3 comm-esr31/mozilla/content/canvas/test/webgl-conformance/writemanifest.py
++--- comm-esr31/mozilla/content/canvas/test/webgl-conformance/writemanifest.py.python3 2014-07-17 18:05:12.000000000 -0600
+++++ comm-esr31/mozilla/content/canvas/test/webgl-conformance/writemanifest.py 2014-10-24 11:41:35.447880278 -0600
++@@ -25,8 +25,10 @@ def listfiles(dir, rel):
++ def writemanifest():
++ script_dir = os.path.dirname(__file__)
++ list_dirs = [os.path.join(script_dir, d) for d in CONFORMANCE_DIRS]
++- with open(os.path.join(script_dir, 'mochitest-conformance-files.ini'), 'w') as f:
+++ f = open(os.path.join(script_dir, 'mochitest-conformance-files.ini'), 'w')
+++ if 1:
++ f.write("""[DEFAULT]
+++ f.close()
++ support-files =
++ %s
++ """ % "\n ".join(sorted(chain.from_iterable(listfiles(d, script_dir)
++diff -up comm-esr31/mozilla/dom/bindings/Codegen.py.python3 comm-esr31/mozilla/dom/bindings/Codegen.py
++--- comm-esr31/mozilla/dom/bindings/Codegen.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/Codegen.py 2014-10-24 11:41:35.450880265 -0600
++@@ -9,7 +9,8 @@ import re
++ import string
++ import math
++ import textwrap
++-
+++from rhrebase import any
+++from rhrebase import all
++ from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue
++ from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
++
++@@ -152,7 +153,7 @@ def fill(template, **args):
++ return t.substitute(args)
++
++
++-class CGThing():
+++class CGThing:
++ """
++ Abstract base class for things that spit out code.
++ """
++@@ -276,8 +277,11 @@ class CGNativePropertyHooks(CGThing):
++ else:
++ prototypeID += "_ID_Count"
++ parent = self.descriptor.interface.parent
++- parentHooks = (toBindingNamespace(parent.identifier.name) + "::sNativePropertyHooks"
++- if parent else 'nullptr')
+++ parentHooks = ""
+++ if parent:
+++ parentHooks = toBindingNamespace(parent.identifier.name) + "::sNativePropertyHooks"
+++ else:
+++ parentHooks = 'nullptr'
++
++ return fill(
++ """
++@@ -300,12 +304,15 @@ class CGNativePropertyHooks(CGThing):
++
++
++ def NativePropertyHooks(descriptor):
++- return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
+++ if descriptor.workers:
+++ return "&sWorkerNativePropertyHooks"
+++ else:
+++ return "sNativePropertyHooks"
++
++
++ def DOMClass(descriptor):
++ def make_name(d):
++- return "%s%s" % (d.interface.identifier.name, '_workers' if d.workers else '')
+++ return "%s%s" % (d.interface.identifier.name, ('', '_workers')[d.workers])
++
++ protoList = ['prototypes::id::' + make_name(descriptor.getDescriptor(proto)) for proto in descriptor.prototypeChain]
++ # Pad out the list to the right length with _ID_Count so we
++@@ -343,7 +350,11 @@ class CGDOMJSClass(CGThing):
++
++ def define(self):
++ traceHook = 'nullptr'
++- callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
+++ callHook = None
+++ if self.descriptor.operations["LegacyCaller"]:
+++ callHook = LEGACYCALLER_HOOK_NAME
+++ else:
+++ callHook = 'nullptr'
++ slotCount = INSTANCE_RESERVED_SLOTS + self.descriptor.interface.totalMembersInSlots
++ classFlags = "JSCLASS_IS_DOMJSCLASS | "
++ classExtensionAndObjectOps = """\
++@@ -426,7 +437,7 @@ JS_NULL_OBJECT_OPS
++ """,
++ name=self.descriptor.interface.identifier.name,
++ flags=classFlags,
++- addProperty=ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'JS_PropertyStub',
+++ addProperty=('JS_PropertyStub', ADDPROPERTY_HOOK_NAME)[wantsAddProperty(self.descriptor)],
++ enumerate=enumerateHook,
++ resolve=newResolveHook,
++ finalize=FINALIZE_HOOK_NAME,
++@@ -454,7 +465,11 @@ class CGDOMProxyJSClass(CGThing):
++ # HTMLAllCollection. So just hardcode it here.
++ if self.descriptor.interface.identifier.name == "HTMLAllCollection":
++ flags.append("JSCLASS_EMULATES_UNDEFINED")
++- callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
+++ callHook = None
+++ if self.descriptor.operations["LegacyCaller"]:
+++ callHook = LEGACYCALLER_HOOK_NAME
+++ else:
+++ callHook = 'nullptr'
++ return fill( # BOGUS extra blank line at the top
++ """
++
++@@ -689,7 +704,12 @@ class CGList(CGThing):
++ self.children.extend(kids)
++
++ def join(self, iterable):
++- return self.joiner.join(s for s in iterable if len(s) > 0)
+++ l = []
+++ for s in iterable:
+++ if len(s) > 0:
+++ l.append(s)
+++
+++ return self.joiner.join(l)
++
++ def declare(self):
++ return self.join(child.declare() for child in self.children if child is not None)
++@@ -840,9 +860,9 @@ class CGElseChain(CGThing):
++
++ class CGTemplatedType(CGWrapper):
++ def __init__(self, templateName, child, isConst=False, isReference=False):
++- const = "const " if isConst else ""
+++ const = ("", "const ")[isConst]
++ pre = "%s%s<" % (const, templateName)
++- ref = "&" if isReference else ""
+++ ref = ("", "&")[isReference]
++ post = ">%s" % ref
++ CGWrapper.__init__(self, child, pre=pre, post=post)
++
++@@ -1280,7 +1300,7 @@ def UnionConversions(descriptors, dictio
++ post="\n\n"))
++
++
++-class Argument():
+++class Argument:
++ """
++ A class for outputting the type and name of an argument
++ """
++@@ -1337,7 +1357,13 @@ class CGAbstractMethod(CGThing):
++ self.templateArgs = templateArgs
++
++ def _argstring(self, declare):
++- return ', '.join([a.declare() if declare else a.define() for a in self.args])
+++ l = []
+++ for a in self.args:
+++ if declare:
+++ l.append(a.declare())
+++ else:
+++ l.append(a.define())
+++ return ', '.join(l)
++
++ def _template(self):
++ if self.templateArgs is None:
++@@ -1353,7 +1379,7 @@ class CGAbstractMethod(CGThing):
++ if self.static:
++ decorators.append('static')
++ decorators.append(self.returnType)
++- maybeNewline = " " if self.inline else "\n"
+++ maybeNewline = ("\n", " ")[self.inline]
++ return ' '.join(decorators) + maybeNewline
++
++ def declare(self):
++@@ -1365,7 +1391,10 @@ class CGAbstractMethod(CGThing):
++ return self.definition_prologue(fromDeclare) + self.definition_body() + self.definition_epilogue()
++
++ def define(self):
++- return "" if self.inline else self._define()
+++ if self.inline:
+++ return ""
+++ else:
+++ return self._define()
++
++ def definition_prologue(self, fromDeclare):
++ return "%s%s%s(%s)\n{\n" % (self._template(), self._decorators(),
++@@ -2184,7 +2213,7 @@ class AttrDefiner(PropertyDefiner):
++ return ""
++
++ def flags(attr):
++- unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
+++ unforgeable = ("", " | JSPROP_PERMANENT")[self.unforgeable]
++ return ("JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS" +
++ unforgeable)
++
++@@ -2265,7 +2294,7 @@ class ConstDefiner(PropertyDefiner):
++ PropertyDefiner.getControllingCondition, specData, doIdArrays)
++
++
++-class PropertyArrays():
+++class PropertyArrays:
++ def __init__(self, descriptor):
++ self.staticMethods = MethodDefiner(descriptor, "StaticMethods",
++ static=True)
++@@ -2299,7 +2328,10 @@ class CGNativeProperties(CGList):
++ def __init__(self, descriptor, properties):
++ def generateNativeProperties(name, chrome):
++ def check(p):
++- return p.hasChromeOnly() if chrome else p.hasNonChromeOnly()
+++ if chrome:
+++ return p.hasChromeOnly()
+++ else:
+++ return p.hasNonChromeOnly()
++
++ nativeProps = []
++ for array in properties.arrayNames():
++@@ -2507,7 +2539,9 @@ class CGCreateInterfaceObjectsMethod(CGA
++ chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr"
++ else:
++ chromeProperties = "nullptr"
++-
+++ back_name = "nullptr"
+++ if needInterfaceObject:
+++ back_name = '"' + self.descriptor.interface.identifier.name + '"'
++ call = fill(
++ """
++ dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
++@@ -2529,7 +2563,7 @@ class CGCreateInterfaceObjectsMethod(CGA
++ domClass=domClass,
++ properties=properties,
++ chromeProperties=chromeProperties,
++- name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
+++ name=back_name)
++
++ if UseHolderForUnforgeable(self.descriptor):
++ assert needInterfacePrototypeObject
++@@ -2765,6 +2799,9 @@ def InitUnforgeablePropertiesOnObject(de
++ """
++ properties is a PropertyArrays instance
++ """
+++ retval = ""
+++ if failureReturnValue:
+++ retval = " " + failureReturnValue
++ defineUnforgeables = fill(
++ """
++ if (!DefineUnforgeableAttributes(aCx, ${obj}, %s)) {
++@@ -2772,7 +2809,7 @@ def InitUnforgeablePropertiesOnObject(de
++ }
++ """,
++ obj=obj,
++- rv=" " + failureReturnValue if failureReturnValue else "")
+++ rv=retval)
++
++ unforgeableAttrs = properties.unforgeableAttrs
++ unforgeables = []
++@@ -3172,6 +3209,8 @@ numericSuffixes = {
++ IDLType.Tags.double: ''
++ }
++
+++def isnan(f):
+++ return str(float(f)) == "nan"
++
++ def numericValue(t, v):
++ if (t == IDLType.Tags.unrestricted_double or
++@@ -3181,12 +3220,12 @@ def numericValue(t, v):
++ return "mozilla::PositiveInfinity<%s>()" % typeName
++ if v == float("-inf"):
++ return "mozilla::NegativeInfinity<%s>()" % typeName
++- if math.isnan(v):
+++ if isnan(v):
++ return "mozilla::UnspecifiedNaN<%s>()" % typeName
++ return "%s%s" % (v, numericSuffixes[t])
++
++
++-class CastableObjectUnwrapper():
+++class CastableObjectUnwrapper:
++ """
++ A class for unwrapping an object named by the "source" argument
++ based on the passed-in descriptor and storing it in a variable
++@@ -3315,7 +3354,7 @@ class CGCallbackTempRoot(CGGeneric):
++ CGGeneric.__init__(self, define=define)
++
++
++-class JSToNativeConversionInfo():
+++class JSToNativeConversionInfo:
++ """
++ An object representing information about a JS-to-native conversion.
++ """
++@@ -3857,11 +3896,17 @@ def getJSToNativeConversionInfo(type, de
++ if nullable:
++ type = type.inner
++
++- unionArgumentObj = "${declName}" if isMember else "${holderName}"
+++ unionArgumentObj = "${holderName}"
+++ if isMember:
+++ unionArgumentObj = "${declName}"
+++ #unionArgumentObj = ("${holderName}", "${declName}")[isMember == true]
++ if nullable:
++ # If we're a member, we're a Nullable, which hasn't been told it has
++ # a value. Otherwise we're an already-constructed Maybe.
++- unionArgumentObj += ".SetValue()" if isMember else ".ref()"
+++ if isMember:
+++ unionArgumentObj += ".SetValue()"
+++ else:
+++ unionArgumentObj += ".ref()"
++
++ memberTypes = type.flatMemberTypes
++ names = []
++@@ -3971,9 +4016,18 @@ def getJSToNativeConversionInfo(type, de
++ templateBody = CGList([templateBody,
++ CGIfWrapper(setDictionary, "!done")])
++
++- stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]
++- numericTypes = [t for t in memberTypes if t.isNumeric()]
++- booleanTypes = [t for t in memberTypes if t.isBoolean()]
+++ stringTypes = []
+++ for t in memberTypes:
+++ if t.isString() or t.isEnum():
+++ stringTypes.append(t)
+++ numericTypes = []
+++ for t in memberTypes:
+++ if t.isNumeric():
+++ numericTypes.append(t)
+++ booleanTypes = []
+++ for t in memberTypes:
+++ if t.isBoolean():
+++ booleanTypes.append(t)
++ if stringTypes or numericTypes or booleanTypes:
++ assert len(stringTypes) <= 1
++ assert len(numericTypes) <= 1
++@@ -4100,7 +4154,7 @@ def getJSToNativeConversionInfo(type, de
++
++ if tag in numericSuffixes or tag is IDLType.Tags.bool:
++ defaultStr = getHandleDefault(defaultValue)
++- value = declLoc + (".Value()" if nullable else "")
+++ value = declLoc + (("", ".Value()")[nullable])
++ default = CGGeneric("%s.RawSetAs%s() = %s;\n" %
++ (value, defaultValue.type, defaultStr))
++ else:
++@@ -4836,17 +4890,19 @@ def instantiateJSToNativeConversion(info
++
++ if checkForValue:
++ if dealWithOptional:
+++ bp_args = ""
+++ if info.declArgs:
+++ bp_args = getArgsCGThing(info.declArgs).define()
++ declConstruct = CGIndenter(
++ CGGeneric("%s.Construct(%s);\n" %
++- (originalDeclName,
++- getArgsCGThing(info.declArgs).define() if
++- info.declArgs else "")))
+++ (originalDeclName, bp_args)))
+++ bp_holderArgs = ""
+++ if info.holderArgs:
+++ bp_holderArgs = getArgsCGThing(info.holderArgs).define()
++ if holderType is not None:
++ holderConstruct = CGIndenter(
++ CGGeneric("%s.construct(%s);\n" %
++- (originalHolderName,
++- getArgsCGThing(info.holderArgs).define() if
++- info.holderArgs else "")))
+++ (originalHolderName, bp_holderArgs)))
++ else:
++ holderConstruct = None
++ else:
++@@ -4880,7 +4936,7 @@ def convertConstIDLValueToJSVal(value):
++ if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
++ return "DOUBLE_TO_JSVAL(%s)" % numericValue(tag, value.value)
++ if tag == IDLType.Tags.bool:
++- return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
+++ return ("JSVAL_FALSE", "JSVAL_TRUE")[value.value]
++ if tag in [IDLType.Tags.float, IDLType.Tags.double]:
++ return "DOUBLE_TO_JSVAL(%s)" % (value.value)
++ raise TypeError("Const value of unhandled type: %s" % value.type)
++@@ -4940,7 +4996,7 @@ class CGArgumentConverter(CGThing):
++ isEnforceRange=self.argument.enforceRange,
++ isClamp=self.argument.clamp,
++ lenientFloatCode=self.lenientFloatCode,
++- isMember="Variadic" if self.argument.variadic else False,
+++ isMember=(False, "Variadic")[self.argument.variadic],
++ allowTreatNonCallableAsNull=self.argument.allowTreatNonCallableAsNull(),
++ sourceDescription=self.argDescription)
++
++@@ -5904,7 +5960,10 @@ def wrapTypeIntoCurrentCompartment(type,
++ if memberWrap:
++ memberWraps.append(memberWrap)
++ myDict = myDict.parent
++- return CGList(memberWraps) if len(memberWraps) != 0 else None
+++ if len(memberWraps) != 0:
+++ return CGList(memberWraps)
+++ else:
+++ return None
++
++ if type.isUnion():
++ memberWraps = []
++@@ -5919,7 +5978,10 @@ def wrapTypeIntoCurrentCompartment(type,
++ memberWrap = CGIfWrapper(
++ memberWrap, "%s.Is%s()" % (value, memberName))
++ memberWraps.append(memberWrap)
++- return CGList(memberWraps, "else ") if len(memberWraps) != 0 else None
+++ if len(memberWraps) != 0:
+++ return CGList(memberWraps, "else ")
+++ else:
+++ return None
++
++ if (type.isString() or type.isPrimitive() or type.isEnum() or
++ type.isGeckoInterface() or type.isCallback() or type.isDate()):
++@@ -6116,8 +6178,11 @@ class CGPerSignatureCall(CGThing):
++ CGIfWrapper(CGList(xraySteps),
++ "objIsXray"))
++
+++ errRep = None
+++ if self.isFallible():
+++ errRep = self.getErrorReport()
++ cgThings.append(CGCallGenerator(
++- self.getErrorReport() if self.isFallible() else None,
+++ errRep,
++ self.getArguments(), argsPre, returnType,
++ self.extendedAttributes, descriptor, nativeMethodName,
++ static, argsPost=argsPost))
++@@ -6151,7 +6216,7 @@ class CGPerSignatureCall(CGThing):
++ 'jsvalHandle': 'args.rval()',
++ 'returnsNewObject': returnsNewObject,
++ 'successCode': successCode,
++- 'obj': "reflector" if setSlot else "obj"
+++ 'obj': ("obj", "reflector")[setSlot]
++ }
++ try:
++ wrapCode = wrapForType(self.returnType, self.descriptor, resultTemplateValues)
++@@ -6490,18 +6555,16 @@ class CGMethodCall(CGThing):
++ # First check for undefined and optional distinguishing arguments
++ # and output a special branch for that case. Note that we don't
++ # use distinguishingArgument here because we actualy want to
++- # exclude variadic arguments. Also note that we skip this check if
++- # we plan to output a isNullOrUndefined() special case for this
+++ # exclude variadic arguments. Also note that we skip this check if # we plan to output a isNullOrUndefined() special case for this
++ # argument anyway, since that will subsume our isUndefined() check.
++ # This is safe, because there can be at most one nullable
++ # distinguishing argument, so if we're it we'll definitely get
++ # picked up by the nullable handling. Also, we can skip this check
++ # if the argument has an unconditional conversion later on.
++- undefSigs = [s for s in possibleSignatures if
++- distinguishingIndex < len(s[1]) and
++- s[1][distinguishingIndex].optional and
++- hasConditionalConversion(s[1][distinguishingIndex].type) and
++- not needsNullOrUndefinedCase(s[1][distinguishingIndex].type)]
+++ undefSigs = []
+++ for s in possibleSignatures:
+++ if distinguishingIndex < len(s[1]) and s[1][distinguishingIndex].optional and hasConditionalConversion(s[1][distinguishingIndex].type) and not needsNullOrUndefinedCase(s[1][distinguishingIndex].type):
+++ undefSigs.append(s)
++ # Can't have multiple signatures with an optional argument at the
++ # same index.
++ assert len(undefSigs) < 2
++@@ -6682,7 +6745,7 @@ class CGGetterCall(CGPerSignatureCall):
++ getter=True)
++
++
++-class FakeArgument():
+++class FakeArgument:
++ """
++ A class that quacks like an IDLArgument. This is used to make
++ setters look like method calls or for special operations.
++@@ -6701,7 +6764,7 @@ class FakeArgument():
++ self.enforceRange = False
++ self.clamp = False
++
++- class FakeIdentifier():
+++ class FakeIdentifier:
++ def __init__(self):
++ self.name = name
++ self.identifier = FakeIdentifier()
++@@ -6858,7 +6921,7 @@ class CGGenericMethod(CGAbstractBindingM
++ unwrapFailureCode = (
++ 'return ThrowInvalidThis(cx, args, GetInvalidThisErrorForMethod(%%(securityError)s), "%s");\n' %
++ descriptor.interface.identifier.name)
++- name = "genericCrossOriginMethod" if allowCrossOriginThis else "genericMethod"
+++ name = ("genericMethod", "genericCrossOriginMethod")[allowCrossOriginThis]
++ CGAbstractBindingMethod.__init__(self, descriptor, name,
++ args,
++ unwrapFailureCode=unwrapFailureCode,
++@@ -7091,7 +7154,7 @@ class CGEnumerateHook(CGAbstractBindingM
++ return prefix + CGAbstractBindingMethod.definition_body(self)
++
++
++-class CppKeywords():
+++class CppKeywords:
++ """
++ A class for checking if method names declared in webidl
++ are not in conflict with C++ keywords.
++@@ -7694,7 +7757,7 @@ class CGMemberJITInfo(CGThing):
++ return "JSJitInfo::Object"
++ if t.isUnion():
++ u = t.unroll()
++- type = "JSJitInfo::Null" if u.hasNullableType else ""
+++ type = ("", "JSJitInfo::Null")[u.hasNullableType]
++ return ("JSJitInfo::ArgType(%s)" %
++ reduce(CGMemberJITInfo.getSingleArgType,
++ u.flatMemberTypes, type))
++@@ -7921,18 +7984,18 @@ def getUnionTypeTemplateVars(unionType,
++ # By the time tryNextCode is invoked, we're guaranteed the union has been
++ # constructed as some type, since we've been trying to convert into the
++ # corresponding member.
++- prefix = "" if ownsMembers else "mUnion."
+++ prefix = ("mUnion.", "")[ownsMembers]
++ tryNextCode = ("%sDestroy%s();\n"
++ "tryNext = true;\n"
++ "return true;\n" % (prefix, name))
++ conversionInfo = getJSToNativeConversionInfo(
++ type, descriptorProvider, failureCode=tryNextCode,
++ isDefinitelyObject=not type.isDictionary(),
++- isMember=("OwningUnion" if ownsMembers else None),
+++ isMember=((None, "OwningUnion")[ownsMembers]),
++ sourceDescription="member of %s" % unionType)
++
++ ctorNeedsCx = conversionInfo.declArgs == "cx"
++- ctorArgs = "cx" if ctorNeedsCx else ""
+++ ctorArgs = ("", "cx")[ctorNeedsCx]
++
++ # This is ugly, but UnionMember needs to call a constructor with no
++ # arguments so the type can't be const.
++@@ -7992,14 +8055,17 @@ def getUnionTypeTemplateVars(unionType,
++ bodyInHeader=not ownsMembers,
++ body=jsConversion)
++
+++ holder = None
+++ if conversionInfo.holderType:
+++ holder = conversionInfo.holderType.define()
++ return {
++ "name": name,
++ "structType": structType,
++ "externalType": externalType,
++ "setter": setter,
++- "holderType": conversionInfo.holderType.define() if conversionInfo.holderType else None,
+++ "holderType": holder,
++ "ctorArgs": ctorArgs,
++- "ctorArgList": [Argument("JSContext*", "cx")] if ctorNeedsCx else []
+++ "ctorArgList": ([], [Argument("JSContext*", "cx")])[ctorNeedsCx]
++ }
++
++
++@@ -8218,8 +8284,16 @@ class CGUnionStruct(CGThing):
++ else:
++ disallowCopyConstruction = True
++
++- friend = " friend class %sArgument;\n" % str(self.type) if not self.ownsMembers else ""
++- bases = [ClassBase("AllOwningUnionBase")] if self.ownsMembers else []
+++ friend = None
+++ if not self.ownsMembers:
+++ friend = " friend class %sArgument;\n" % str(self.type)
+++ else:
+++ friend = ""
+++ bases = None
+++ if self.ownsMembers:
+++ bases = [ClassBase("AllOwningUnionBase")]
+++ else:
+++ bases = []
++ return CGClass(selfName,
++ bases=bases,
++ members=members,
++@@ -8257,7 +8331,10 @@ class CGUnionStruct(CGThing):
++ Returns a string name for this known union type.
++ """
++ assert type.isUnion() and not type.nullable()
++- return ("Owning" if ownsMembers else "") + type.name
+++ if ownsMembers:
+++ return "Owning" + type.name
+++ else:
+++ return type.name
++
++ @staticmethod
++ def unionTypeDecl(type, ownsMembers):
++@@ -8408,8 +8485,11 @@ class ClassMethod(ClassItem):
++ return self.body
++
++ def declare(self, cgClass):
++- templateClause = ('template <%s>\n' % ', '.join(self.templateArgs)
++- if self.bodyInHeader and self.templateArgs else '')
+++ templateClause = None
+++ if self.bodyInHeader and self.templateArgs:
+++ templateClause = ('template <%s>\n' % ', '.join(self.templateArgs))
+++ else:
+++ templateClause = ('')
++ args = ', '.join([a.declare() for a in self.args])
++ if self.bodyInHeader:
++ body = indent(self.getBody())
++@@ -8427,8 +8507,8 @@ class ClassMethod(ClassItem):
++ breakAfterReturnDecl=self.breakAfterReturnDecl,
++ name=self.name,
++ args=args,
++- const=' const' if self.const else '',
++- override=' MOZ_OVERRIDE' if self.override else '',
+++ const=('', ' const')[self.const],
+++ override=('', ' MOZ_OVERRIDE')[self.override],
++ body=body,
++ breakAfterSelf=self.breakAfterSelf)
++
++@@ -8462,7 +8542,7 @@ class ClassMethod(ClassItem):
++ className=cgClass.getNameString(),
++ name=self.name,
++ args=', '.join([a.define() for a in self.args]),
++- const=' const' if self.const else '',
+++ const=('', ' const')[self.const],
++ body=self.getBody())
++
++
++@@ -8653,7 +8733,7 @@ class ClassMember(ClassItem):
++ ClassItem.__init__(self, name, visibility)
++
++ def declare(self, cgClass):
++- return '%s%s %s;\n' % ('static ' if self.static else '', self.type,
+++ return '%s%s %s;\n' % (('', 'static ')[self.static], self.type,
++ self.name)
++
++ def define(self, cgClass):
++@@ -8694,7 +8774,7 @@ class ClassEnum(ClassItem):
++ else:
++ entry = '%s = %s' % (self.entries[i], self.values[i])
++ entries.append(entry)
++- name = '' if not self.name else ' ' + self.name
+++ name = (' ','')[not self.name] + self.name
++ return 'enum%s\n{\n%s\n};\n' % (name, indent(',\n'.join(entries)))
++
++ def define(self, cgClass):
++@@ -8731,7 +8811,11 @@ class CGClass(CGThing):
++ self.constructors = constructors
++ # We store our single destructor in a list, since all of our
++ # code wants lists of members.
++- self.destructors = [destructor] if destructor else []
+++ self.destructors = None
+++ if destructor:
+++ self.destructors = [destructor]
+++ else:
+++ self.destructors = []
++ self.methods = methods
++ self.typedefs = typedefs
++ self.enums = enums
++@@ -8741,7 +8825,7 @@ class CGClass(CGThing):
++ self.isStruct = isStruct
++ self.disallowCopyConstruction = disallowCopyConstruction
++ self.indent = indent
++- self.defaultVisibility = 'public' if isStruct else 'private'
+++ self.defaultVisibility = ('private','public')[isStruct]
++ self.decorators = decorators
++ self.extradeclarations = extradeclarations
++ self.extradefinitions = extradefinitions
++@@ -8761,7 +8845,7 @@ class CGClass(CGThing):
++ result += ('template <%s>\n' %
++ ','.join([str(a) for a in templateArgs]))
++
++- type = 'struct' if self.isStruct else 'class'
+++ type = ('class', 'struct')[self.isStruct]
++
++ if self.templateSpecialization:
++ specialization = \
++@@ -8998,7 +9082,7 @@ class CGClassForwardDeclare(CGThing):
++ self.isStruct = isStruct
++
++ def declare(self):
++- type = 'struct' if self.isStruct else 'class'
+++ type = ('class', 'struct')[self.isStruct]
++ return '%s %s;\n' % (type, self.name)
++
++ def define(self):
++@@ -10078,7 +10162,7 @@ class CGDOMJSProxyHandlerDefiner(CGThing
++
++
++ def stripTrailingWhitespace(text):
++- tail = '\n' if text.endswith('\n') else ''
+++ tail = ('', '\n')[text.endswith('\n')]
++ lines = text.splitlines()
++ return '\n'.join(line.rstrip() for line in lines) + tail
++
++@@ -11005,8 +11089,10 @@ def dependencySortObjects(objects, depen
++ while len(objects) != 0:
++ # Find the dictionaries that don't depend on anything else
++ # anymore and move them over.
++- toMove = [o for o in objects if
++- len(dependencyGetter(o) & objects) == 0]
+++ toMove = []
+++ for o in objects:
+++ if len(dependencyGetter(o) & objects) == 0:
+++ toMove.append(o)
++ if len(toMove) == 0:
++ raise TypeError("Loop in dependency graph\n" +
++ "\n".join(o.location for o in objects))
++@@ -11273,14 +11359,16 @@ class CGBindingRoot(CGThing):
++ cgthings.extend([CGDescriptor(x) for x in descriptors])
++
++ # Do codegen for all the callback interfaces. Skip worker callbacks.
++- cgthings.extend([CGCallbackInterface(x) for x in callbackDescriptors if
++- not x.workers])
+++ cgthings.extend([CGCallbackInterface(x) for x in callbackDescriptors if not x.workers])
++
++ # Do codegen for JS implemented classes
++ def getParentDescriptor(desc):
++ if not desc.interface.parent:
++- return set()
++- return {desc.getDescriptor(desc.interface.parent.identifier.name)}
+++ return set()
+++ #return (desc.getDescriptor(desc.interface.parent.identifier.name))
+++ s = set()
+++ s.add(desc.getDescriptor(desc.interface.parent.identifier.name))
+++ return s
++ for x in dependencySortObjects(jsImplemented, getParentDescriptor,
++ lambda d: d.interface.identifier.name):
++ cgthings.append(CGCallbackInterface(x))
++@@ -11363,7 +11451,7 @@ class CGNativeMember(ClassMethod):
++ self.passJSBitsAsNeeded = passJSBitsAsNeeded
++ self.jsObjectsArePtr = jsObjectsArePtr
++ self.variadicIsSequence = variadicIsSequence
++- breakAfterSelf = "\n" if breakAfter else ""
+++ breakAfterSelf = ("", "\n")[breakAfter]
++ ClassMethod.__init__(self, name,
++ self.getReturnType(signature[0], False),
++ self.getArgs(signature[0], signature[1]),
++@@ -11723,7 +11811,7 @@ class CGNativeMember(ClassMethod):
++ decl = CGTemplatedType("Nullable", decl)
++ ref = True
++ if isMember == "Variadic":
++- arrayType = "Sequence" if self.variadicIsSequence else "nsTArray"
+++ arrayType = ("nsTArray", "Sequence")[self.variadicIsSequence]
++ decl = CGTemplatedType(arrayType, decl)
++ ref = True
++ elif optional:
++@@ -11739,7 +11827,7 @@ class CGNativeMember(ClassMethod):
++ """
++ decl, ref = self.getArgType(arg.type,
++ arg.optional and not arg.defaultValue,
++- "Variadic" if arg.variadic else False)
+++ (False, "Variadic")[arg.variadic])
++ if ref:
++ decl = CGWrapper(decl, pre="const ", post="&")
++
++@@ -12065,7 +12153,7 @@ class CGExampleClass(CGBindingImplClass)
++ return string.Template(classImpl).substitute(
++ ifaceName=self.descriptor.name,
++ nativeType=self.nativeLeafName(self.descriptor),
++- parentType=self.nativeLeafName(self.parentDesc) if self.parentIface else "")
+++ parentType=("", self.nativeLeafName(self.parentDesc))[self.parentIface])
++
++ @staticmethod
++ def nativeLeafName(descriptor):
++@@ -12639,7 +12727,7 @@ class CGCallbackInterface(CGCallback):
++ methods, getters=getters, setters=setters)
++
++
++-class FakeMember():
+++class FakeMember:
++ def __init__(self):
++ self.treatNullAs = "Default"
++
++@@ -12684,7 +12772,7 @@ class CallbackMember(CGNativeMember):
++ self.needThisHandling = needThisHandling
++ # If needThisHandling, we generate ourselves as private and the caller
++ # will handle generating public versions that handle the "this" stuff.
++- visibility = "private" if needThisHandling else "public"
+++ visibility = ("public", "private")[needThisHandling]
++ self.rethrowContentException = rethrowContentException
++ # We don't care, for callback codegen, whether our original member was
++ # a method or attribute or whatnot. Just always pass FakeMember()
++@@ -12806,7 +12894,7 @@ class CallbackMember(CGNativeMember):
++ arg.type, self.descriptorProvider,
++ {
++ 'result': result,
++- 'successCode': "continue;\n" if arg.variadic else "break;\n",
+++ 'successCode': ("break;\n", "continue;\n")[arg.variadic],
++ 'jsvalRef': "argv.handleAt(%s)" % jsvalIndex,
++ 'jsvalHandle': "argv.handleAt(%s)" % jsvalIndex,
++ # XXXbz we don't have anything better to use for 'obj',
++@@ -12816,7 +12904,7 @@ class CallbackMember(CGNativeMember):
++ 'returnsNewObject': False,
++ 'exceptionCode': self.exceptionCode
++ })
++- except MethodNotNewObjectError as err:
+++ except MethodNotNewObjectError, err:
++ raise TypeError("%s being passed as an argument to %s but is not "
++ "wrapper cached, so can't be reliably converted to "
++ "a JS object." %
++@@ -12901,7 +12989,7 @@ class CallbackMember(CGNativeMember):
++
++ @staticmethod
++ def ensureASCIIName(idlObject):
++- type = "attribute" if idlObject.isAttr() else "operation"
+++ type = ("operation", "attribute")[idlObject.isAttr()]
++ if re.match("[^\x20-\x7E]", idlObject.identifier.name):
++ raise SyntaxError('Callback %s name "%s" contains non-ASCII '
++ "characters. We can't handle that. %s" %
++@@ -13124,7 +13212,7 @@ class CGJSImplInitOperation(CallbackOper
++ return "__init"
++
++
++-class GlobalGenRoots():
+++class GlobalGenRoots:
++ """
++ Roots for global codegen.
++
++@@ -13473,7 +13561,7 @@ class CGEventMethod(CGNativeMember):
++ def getArg(self, arg):
++ decl, ref = self.getArgType(arg.type,
++ arg.optional and not arg.defaultValue,
++- "Variadic" if arg.variadic else False)
+++ (False, "Variadic")[arg.variadic])
++ if ref:
++ decl = CGWrapper(decl, pre="const ", post="&")
++
++@@ -13676,8 +13764,7 @@ class CGEventClass(CGBindingImplClass):
++ dropJS += "mozilla::DropJSObjects(this);\n"
++ # Just override CGClass and do our own thing
++ nativeType = self.descriptor.nativeType.split('::')[-1]
++- ctorParams = ("aOwner, nullptr, nullptr" if self.parentType == "Event"
++- else "aOwner")
+++ ctorParams = (("aOwner", "aOwner, nullptr, nullptr")[self.parentType == "Event"])
++
++ classImpl = fill(
++ """
++diff -up comm-esr31/mozilla/dom/bindings/Configuration.py.python3 comm-esr31/mozilla/dom/bindings/Configuration.py
++--- comm-esr31/mozilla/dom/bindings/Configuration.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/Configuration.py 2014-10-24 11:41:35.451880261 -0600
++@@ -3,6 +3,7 @@
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++ from WebIDL import IDLInterface, IDLExternalInterface
+++from rhrebase import any, all
++ import os
++
++ autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
++@@ -95,8 +96,7 @@ class Configuration:
++ (workerCallbacks, workerDictionaries) = findCallbacksAndDictionaries(workerTypes)
++
++ self.dictionaries = [d for d in parseData if d.isDictionary()]
++- self.callbacks = [c for c in parseData if
++- c.isCallback() and not c.isInterface()]
+++ self.callbacks = [c for c in parseData if c.isCallback() and not c.isInterface()]
++
++ def flagWorkerOrMainThread(items, main, worker):
++ for item in items:
++@@ -380,7 +380,10 @@ class Descriptor(DescriptorProvider):
++ desc.get('wrapperCache', True)))
++
++ def make_name(name):
++- return name + "_workers" if self.workers else name
+++ if self.workers:
+++ return name + "_workers"
+++ else:
+++ return name
++ self.name = make_name(interface.identifier.name)
++
++ # self.extendedAttributes is a dict of dicts, keyed on
++@@ -463,10 +466,10 @@ class Descriptor(DescriptorProvider):
++
++ assert member.isAttr()
++ assert bool(getter) != bool(setter)
++- key = 'getterOnly' if getter else 'setterOnly'
+++ key = ('setterOnly', 'getterOnly')[getter]
++ attrs = self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, [])
++ if throws is None:
++- throwsAttr = "GetterThrows" if getter else "SetterThrows"
+++ throwsAttr = ("SetterThrows", "GetterThrows")[getter]
++ throws = member.getExtendedAttribute(throwsAttr)
++ maybeAppendInfallibleToAttrs(attrs, throws)
++ return attrs
++diff -up comm-esr31/mozilla/dom/bindings/mach_commands.py.python3 comm-esr31/mozilla/dom/bindings/mach_commands.py
++--- comm-esr31/mozilla/dom/bindings/mach_commands.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/mach_commands.py 2014-10-24 11:41:35.451880261 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import sys
++diff -up comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/__init__.py.python3 comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/__init__.py
++--- comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/__init__.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/__init__.py 2014-10-24 11:41:35.451880261 -0600
++@@ -5,11 +5,11 @@
++ # This module contains code for managing WebIDL files and bindings for
++ # the build system.
++
++-from __future__ import unicode_literals
+++
++
++ import errno
++-import hashlib
++-import json
+++import md5, sha
+++import simplejson as json
++ import logging
++ import os
++
++@@ -126,20 +126,20 @@ class WebIDLCodegenManager(LoggingMixin)
++ """
++
++ # Global parser derived declaration files.
++- GLOBAL_DECLARE_FILES = {
+++ GLOBAL_DECLARE_FILES = [
++ 'GeneratedAtomList.h',
++ 'PrototypeList.h',
++ 'RegisterBindings.h',
++ 'UnionConversions.h',
++ 'UnionTypes.h',
++- }
+++ ]
++
++ # Global parser derived definition files.
++- GLOBAL_DEFINE_FILES = {
+++ GLOBAL_DEFINE_FILES = [
++ 'RegisterBindings.cpp',
++ 'UnionTypes.cpp',
++ 'PrototypeList.cpp',
++- }
+++ ]
++
++ def __init__(self, config_path, inputs, exported_header_dir,
++ codegen_dir, state_path, cache_dir=None, make_deps_path=None,
++@@ -188,13 +188,15 @@ class WebIDLCodegenManager(LoggingMixin)
++ self._state = WebIDLCodegenManagerState()
++
++ if os.path.exists(state_path):
++- with open(state_path, 'rb') as fh:
+++ fh = open(state_path, 'rb')
+++ if 1:
++ try:
++ self._state = WebIDLCodegenManagerState(fh=fh)
++- except Exception as e:
+++ except Exception, e:
++ self.log(logging.WARN, 'webidl_bad_state', {'msg': str(e)},
++ 'Bad WebIDL state: {msg}')
++
+++ fh.close()
++ @property
++ def config(self):
++ if not self._config:
++@@ -212,8 +214,7 @@ class WebIDLCodegenManager(LoggingMixin)
++ are present and up to date.
++
++ This routine is called as part of the build to ensure files that need
++- to exist are present and up to date. This routine may not be called if
++- the build dependencies (generated as a result of calling this the first
+++ to exist are present and up to date. This routine may not be called if the build dependencies (generated as a result of calling this the first
++ time) say everything is up to date.
++
++ Because reprocessing outputs for every .webidl on every invocation
++@@ -286,9 +287,11 @@ class WebIDLCodegenManager(LoggingMixin)
++ codegen_rule.add_dependencies(global_hashes.keys())
++ codegen_rule.add_dependencies(self._input_paths)
++
++- with FileAvoidWrite(self._make_deps_path) as fh:
+++ fh = FileAvoidWrite(self._make_deps_path).__enter__()
+++ if 1:
++ mk.dump(fh)
++
+++ fh.__exit__(0, 0, 0)
++ self._save_state()
++
++ return result
++@@ -313,11 +316,13 @@ class WebIDLCodegenManager(LoggingMixin)
++ parser = WebIDL.Parser(self._cache_dir)
++
++ for path in sorted(self._input_paths):
++- with open(path, 'rb') as fh:
+++ fh = open(path, 'rb')
+++ if 1:
++ data = fh.read()
++- hashes[path] = hashlib.sha1(data).hexdigest()
+++ hashes[path] = sha.sha(data).hexdigest()
++ parser.parse(data, path)
++
+++ fh.close()
++ self._parser_results = parser.finish()
++ self._config = Configuration(self._config_path, self._parser_results)
++ self._input_hashes = hashes
++@@ -363,8 +368,12 @@ class WebIDLCodegenManager(LoggingMixin)
++ # a lot of extra work and most build systems don't do that anyway.
++
++ # Now we move on to the input files.
++- old_hashes = {v['filename']: v['sha1']
++- for v in self._state['webidls'].values()}
+++ old_hashes = {}
+++ for v in self._state['webidls'].values():
+++ old_hashes[v['filename']] = v['sha1']
+++
+++ #old_hashes = {v['filename']: v['sha1']
+++ # for v in self._state['webidls'].values()}
++
++ old_filenames = set(old_hashes.keys())
++ new_filenames = self._input_paths
++@@ -416,11 +425,16 @@ class WebIDLCodegenManager(LoggingMixin)
++
++ is_event = stem in self._generated_events_stems
++
+++ my_header_dir = None
+++ my_codegen_dir = None
+++ if is_event:
+++ my_header_dir = mozpath.join(header_dir, '%s.h' % stem)
+++ my_codegen_dir = mozpath.join(self._codegen_dir, '%s.cpp' % stem)
++ files = (
++ mozpath.join(header_dir, '%s.h' % binding_stem),
++ mozpath.join(self._codegen_dir, '%s.cpp' % binding_stem),
++- mozpath.join(header_dir, '%s.h' % stem) if is_event else None,
++- mozpath.join(self._codegen_dir, '%s.cpp' % stem) if is_event else None,
+++ my_header_dir,
+++ my_codegen_dir,
++ )
++
++ return stem, binding_stem, is_event, header_dir, files
++@@ -442,7 +456,9 @@ class WebIDLCodegenManager(LoggingMixin)
++
++ for p in self._input_paths:
++ stem, binding_stem, is_event, header_dir, files = self._binding_info(p)
++- paths |= {f for f in files if f}
+++ for f in files:
+++ if f:
+++ paths.add(f);
++
++ for interface in self._example_interfaces:
++ for p in self._example_paths(interface):
++@@ -484,11 +500,12 @@ class WebIDLCodegenManager(LoggingMixin)
++
++ current_hashes = {}
++ for f in current_files:
++- # This will fail if the file doesn't exist. If a current global
++- # dependency doesn't exist, something else is wrong.
++- with open(f, 'rb') as fh:
++- current_hashes[f] = hashlib.sha1(fh.read()).hexdigest()
+++ # This will failthe file doesn't exist. If a current global # dependency doesn't exist, something = (is wrong., )[]
+++ fh = open(f, 'rb')
+++ if 1:
+++ current_hashes[f] = sha.sha(fh.read()).hexdigest()
++
+++ fh.close()
++ # The set of files has changed.
++ if current_files ^ set(self._state['global_depends'].keys()):
++ return True, current_hashes
++@@ -501,9 +518,11 @@ class WebIDLCodegenManager(LoggingMixin)
++ return False, current_hashes
++
++ def _save_state(self):
++- with open(self._state_path, 'wb') as fh:
+++ fh = open(self._state_path, 'wb')
+++ if 1:
++ self._state.dump(fh)
++
+++ fh.close()
++ def _maybe_write_codegen(self, obj, declare_path, define_path, result=None):
++ assert declare_path and define_path
++ if not result:
++@@ -532,16 +551,18 @@ def create_build_system_manager(topsrcdi
++ src_dir = os.path.join(topsrcdir, 'dom', 'bindings')
++ obj_dir = os.path.join(topobjdir, 'dom', 'bindings')
++
++- with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh:
+++ fh = open(os.path.join(obj_dir, 'file-lists.json'), 'rb')
+++ if 1:
++ files = json.load(fh)
++
+++ fh.close()
++ inputs = (files['webidls'], files['exported_stems'],
++ files['generated_events_stems'], files['example_interfaces'])
++
++ cache_dir = os.path.join(obj_dir, '_cache')
++ try:
++ os.makedirs(cache_dir)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++
++diff -up comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py.python3 comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py
++--- comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py 2014-10-24 11:41:35.452880257 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import imp
++ import json
++@@ -89,12 +89,14 @@ class TestWebIDLCodegenManager(unittest.
++
++ p = args['state_path']
++
++- with open(p, 'wb') as fh:
+++ fh = open(p, 'wb')
+++ if 1:
++ json.dump({
++ 'version': WebIDLCodegenManagerState.VERSION + 1,
++ 'foobar': '1',
++ }, fh)
++
+++ fh.close()
++ manager = WebIDLCodegenManager(**args)
++
++ self.assertEqual(manager._state['version'],
++@@ -129,7 +131,8 @@ class TestWebIDLCodegenManager(unittest.
++
++ self.assertTrue(os.path.isfile(manager._state_path))
++
++- with open(manager._state_path, 'rb') as fh:
+++ fh = open(manager._state_path, 'rb')
+++ if 1:
++ state = json.load(fh)
++ self.assertEqual(state['version'], 1)
++ self.assertIn('webidls', state)
++@@ -139,6 +142,7 @@ class TestWebIDLCodegenManager(unittest.
++ self.assertEqual(len(child['outputs']), 2)
++ self.assertEqual(child['sha1'], 'c41527cad3bc161fa6e7909e48fa11f9eca0468b')
++
+++ fh.close()
++ def test_generate_build_files_load_state(self):
++ """State should be equivalent when instantiating a new instance."""
++ args = self._get_manager_args()
++@@ -197,13 +201,15 @@ class TestWebIDLCodegenManager(unittest.
++ self.assertIsNotNone(child_path)
++ child_content = open(child_path, 'rb').read()
++
++- with MockedOpen({child_path: child_content + '\n/* */'}):
+++ MockedOpen({child_path: child_content + '\n/* */'}).__enter__()
+++ if 1:
++ m2 = WebIDLCodegenManager(**args)
++ result = m2.generate_build_files()
++ self.assertEqual(result.inputs, set([child_path]))
++ self.assertEqual(len(result.updated), 0)
++ self.assertEqual(len(result.created), 0)
++
+++ MockedOpen({child_path: child_content + '\n/* */'}).__exit__(0, 0, 0)
++ def test_rebuild_dependencies(self):
++ """Ensure an input file used by others results in others rebuilding."""
++ args = self._get_manager_args()
++@@ -221,13 +227,15 @@ class TestWebIDLCodegenManager(unittest.
++ self.assertIsNotNone(parent_path)
++ parent_content = open(parent_path, 'rb').read()
++
++- with MockedOpen({parent_path: parent_content + '\n/* */'}):
+++ MockedOpen({parent_path: parent_content + '\n/* */'}).__enter__()
+++ if 1:
++ m2 = WebIDLCodegenManager(**args)
++ result = m2.generate_build_files()
++ self.assertEqual(result.inputs, {child_path, parent_path})
++ self.assertEqual(len(result.updated), 0)
++ self.assertEqual(len(result.created), 0)
++
+++ MockedOpen({parent_path: parent_content + '\n/* */'}).__exit__(0, 0, 0)
++ def test_python_change_regenerate_everything(self):
++ """If a Python file changes, we should attempt to rebuild everything."""
++
++@@ -240,7 +248,8 @@ class TestWebIDLCodegenManager(unittest.
++ # the first iteration we read from a temp file. The second iteration
++ # doesn't need to import, so we are fine with a mocked file.
++ fake_path = mozpath.join(OUR_DIR, 'fakemodule.py')
++- with NamedTemporaryFile('wt') as fh:
+++ fh = NamedTemporaryFile('wt').__enter__()
+++ if 1:
++ fh.write('# Original content')
++ fh.flush()
++ mod = imp.load_source('mozwebidlcodegen.fakemodule', fh.name)
++@@ -248,7 +257,8 @@ class TestWebIDLCodegenManager(unittest.
++
++ args = self._get_manager_args()
++ m1 = WebIDLCodegenManager(**args)
++- with MockedOpen({fake_path: '# Original content'}):
+++ MockedOpen({fake_path: '# Original content'}).__enter__()
+++ if 1:
++ old_exists = os.path.exists
++ try:
++ def exists(p):
++@@ -274,6 +284,8 @@ class TestWebIDLCodegenManager(unittest.
++ os.path.exists = old_exists
++ del sys.modules['mozwebidlcodegen.fakemodule']
++
+++ MockedOpen({fake_path: '# Original content'}).__exit__(0, 0, 0)
+++ fh.close()
++ def test_copy_input(self):
++ """Ensure a copied .webidl file is handled properly."""
++
++diff -up comm-esr31/mozilla/dom/bindings/parser/tests/test_distinguishability.py.python3 comm-esr31/mozilla/dom/bindings/parser/tests/test_distinguishability.py
++--- comm-esr31/mozilla/dom/bindings/parser/tests/test_distinguishability.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/parser/tests/test_distinguishability.py 2014-10-24 11:41:35.452880257 -0600
++@@ -89,11 +89,11 @@ def WebIDLTest(parser, harness):
++ harness.check(type1.isDistinguishableFrom(type2),
++ distinguishable,
++ "Type %s should %sbe distinguishable from type %s" %
++- (type1, "" if distinguishable else "not ", type2))
+++ (type1, ("not ", "")[distinguishable], type2))
++ harness.check(type2.isDistinguishableFrom(type1),
++ distinguishable,
++ "Type %s should %sbe distinguishable from type %s" %
++- (type2, "" if distinguishable else "not ", type1))
+++ (type2, ("not ", "")[distinguishable], type1))
++
++ parser = parser.reset()
++ parser.parse("""
++diff -up comm-esr31/mozilla/dom/bindings/parser/tests/test_float_types.py.python3 comm-esr31/mozilla/dom/bindings/parser/tests/test_float_types.py
++--- comm-esr31/mozilla/dom/bindings/parser/tests/test_float_types.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/parser/tests/test_float_types.py 2014-10-24 11:41:35.452880257 -0600
++@@ -57,7 +57,7 @@ def WebIDLTest(parser, harness):
++ harness.ok(type.isFloat(), "Type %d should be float" % idx)
++ harness.check(type.isUnrestricted(), idx >= 5,
++ "Type %d should %sbe unrestricted" % (
++- idx, "" if idx >= 4 else "not "))
+++ idx, ("not ","")[idx >= 4]))
++
++ parser = parser.reset()
++ threw = False
++diff -up comm-esr31/mozilla/dom/bindings/parser/WebIDL.py.python3 comm-esr31/mozilla/dom/bindings/parser/WebIDL.py
++--- comm-esr31/mozilla/dom/bindings/parser/WebIDL.py.python3 2014-07-17 18:05:14.000000000 -0600
+++++ comm-esr31/mozilla/dom/bindings/parser/WebIDL.py 2014-10-24 11:41:35.453880252 -0600
++@@ -9,6 +9,7 @@ import re
++ import os
++ import traceback
++ import math
+++from rhrebase import any, all
++
++ # Machinery
++
++@@ -69,7 +70,7 @@ class WebIDLError(Exception):
++ def __str__(self):
++ return "%s: %s%s%s" % (self.warning and 'warning' or 'error',
++ self.message,
++- ", " if len(self.locations) != 0 else "",
+++ ("", ", ")[len(self.locations) != 0],
++ "\n".join(self.locations))
++
++ class Location(object):
++@@ -78,7 +79,11 @@ class Location(object):
++ self._lineno = lineno
++ self._lexpos = lexpos
++ self._lexdata = lexer.lexdata
++- self._file = filename if filename else "<unknown>"
+++ self._file = None
+++ if filename:
+++ self._file = filename
+++ else:
+++ self._file = "<unknown>"
++
++ def __eq__(self, other):
++ return self._lexpos == other._lexpos and \
++@@ -551,7 +556,11 @@ class IDLInterface(IDLObjectWithScope):
++ [self.location])
++
++ assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
++- parent = self.parent.finish(scope) if self.parent else None
+++ parent = None
+++ if self.parent:
+++ parent = self.parent.finish(scope)
+++ else:
+++ parent = None
++ if parent and isinstance(parent, IDLExternalInterface):
++ raise WebIDLError("%s inherits from %s which does not have "
++ "a definition" %
++@@ -561,8 +570,8 @@ class IDLInterface(IDLObjectWithScope):
++ assert not parent or isinstance(parent, IDLInterface)
++
++ self.parent = parent
++-
++- assert iter(self.members)
+++ #print "SELF_MEMB", self.members
+++ # we may ignore it, empty array is also iterable in python 2.6 assert iter(self.members)
++
++ if self.parent:
++ self.parent.finish(scope)
++@@ -685,11 +694,9 @@ class IDLInterface(IDLObjectWithScope):
++ # worry about anything other than our parent, because it has already
++ # imported its ancestors unforgeable attributes into its member
++ # list.
++- for unforgeableAttr in (attr for attr in self.parent.members if
++- attr.isAttr() and not attr.isStatic() and
+++ for unforgeableAttr in (attr for attr in self.parent.members if attr.isAttr() and not attr.isStatic() and
++ attr.isUnforgeable()):
++- shadows = [ m for m in self.members if
++- (m.isAttr() or m.isMethod()) and
+++ shadows = [ m for m in self.members if (m.isAttr() or m.isMethod()) and
++ not m.isStatic() and
++ m.identifier.name == unforgeableAttr.identifier.name ]
++ if len(shadows) != 0:
++@@ -853,8 +860,7 @@ class IDLInterface(IDLObjectWithScope):
++ not any(m.isAttr() for m in self.members) and
++ # There is at least one regular operation, and all regular
++ # operations have the same identifier
++- len(set(m.identifier.name for m in self.members if
++- m.isMethod() and not m.isStatic())) == 1)
+++ len(set(m.identifier.name for m in self.members if m.isMethod() and not m.isStatic())) == 1)
++
++ def inheritanceDepth(self):
++ depth = 0
++@@ -910,7 +916,11 @@ class IDLInterface(IDLObjectWithScope):
++ raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
++ [self.location])
++
++- args = attr.args() if attr.hasArgs() else []
+++ args = None
+++ if attr.hasArgs():
+++ args = attr.args()
+++ else:
+++ args = []
++
++ retType = IDLWrapperType(self.location, self)
++
++@@ -995,7 +1005,8 @@ class IDLInterface(IDLObjectWithScope):
++ [attr.location])
++
++ attrlist = attr.listValue()
++- self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
+++
+++ self._extendedAttrDict[identifier] = (True, attrlist)[len(attrlist) > 0]
++
++ def addImplementedInterface(self, implementedInterface):
++ assert(isinstance(implementedInterface, IDLInterface))
++@@ -2666,7 +2677,7 @@ class IDLInterfaceMember(IDLObjectWithId
++ for attr in attrs:
++ self.handleExtendedAttribute(attr)
++ attrlist = attr.listValue()
++- self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True
+++ self._extendedAttrDict[attr.identifier()] = (True, attrlist)[len(attrlist)]
++
++ def handleExtendedAttribute(self, attr):
++ pass
++@@ -3420,8 +3431,7 @@ class IDLMethod(IDLInterfaceMember, IDLS
++ [self.location, overload.location])
++
++ def overloadsForArgCount(self, argc):
++- return [overload for overload in self._overloads if
++- len(overload.arguments) == argc or
+++ return [overload for overload in self._overloads if len(overload.arguments) == argc or
++ (len(overload.arguments) > argc and
++ all(arg.optional for arg in overload.arguments[argc:])) or
++ (len(overload.arguments) < argc and
++@@ -3890,7 +3900,10 @@ class Parser(Tokenizer):
++ """
++ InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
++ """
++- p[0] = [p[2]] if p[2] else []
+++ if p[2]:
+++ p[0] = [p[2]]
+++ else:
+++ p[0] = []
++
++ assert not p[1] or p[2]
++ p[2].addExtendedAttributes(p[1])
++@@ -4183,11 +4196,27 @@ class Parser(Tokenizer):
++ # by the parser, so we can assert here.
++ assert not stringifier or len(qualifiers) == 1
++
++- getter = True if IDLMethod.Special.Getter in p[1] else False
++- setter = True if IDLMethod.Special.Setter in p[1] else False
++- creator = True if IDLMethod.Special.Creator in p[1] else False
++- deleter = True if IDLMethod.Special.Deleter in p[1] else False
++- legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
+++ getter = False
+++ if IDLMethod.Special.Getter in p[1]:
+++ getter = True
+++ else:
+++ getter = False
+++ setter = False
+++ if IDLMethod.Special.Setter in p[1]:
+++ setter = True
+++ creator = None
+++ if IDLMethod.Special.Creator in p[1]:
+++ creator = True
+++ else:
+++ creator = False
+++ deleter = False
+++ if IDLMethod.Special.Deleter in p[1]:
+++ deleter = True
+++ legacycaller = None
+++ if IDLMethod.Special.LegacyCaller in p[1]:
+++ legacycaller = True
+++ else:
+++ legacycaller = False
++
++ if getter or deleter:
++ if setter or creator:
++@@ -4203,7 +4232,7 @@ class Parser(Tokenizer):
++ if getter or deleter:
++ if len(arguments) != 1:
++ raise WebIDLError("%s has wrong number of arguments" %
++- ("getter" if getter else "deleter"),
+++ (("deleter", "getter")[getter]),
++ [self.getLocation(p, 2)])
++ argType = arguments[0].type
++ if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
++@@ -4212,12 +4241,11 @@ class Parser(Tokenizer):
++ specialType = IDLMethod.NamedOrIndexed.Indexed
++ else:
++ raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
++- ("getter" if getter else "deleter"),
+++ (("deleter", "getter")[getter]),
++ [arguments[0].location])
++ if arguments[0].optional or arguments[0].variadic:
++ raise WebIDLError("%s cannot have %s argument" %
++- ("getter" if getter else "deleter",
++- "optional" if arguments[0].optional else "variadic"),
+++ (("deleter", "getter")[getter], ("variadic", "optional")[garguments[0].optional]),
++ [arguments[0].location])
++ if getter:
++ if returnType.isVoid():
++@@ -4226,7 +4254,7 @@ class Parser(Tokenizer):
++ if setter or creator:
++ if len(arguments) != 2:
++ raise WebIDLError("%s has wrong number of arguments" %
++- ("setter" if setter else "creator"),
+++ (("creator", "setter")[setter]),
++ [self.getLocation(p, 2)])
++ argType = arguments[0].type
++ if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
++@@ -4235,17 +4263,15 @@ class Parser(Tokenizer):
++ specialType = IDLMethod.NamedOrIndexed.Indexed
++ else:
++ raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
++- ("setter" if setter else "creator"),
+++ (("creator", "setter")[setter]),
++ [arguments[0].location])
++ if arguments[0].optional or arguments[0].variadic:
++ raise WebIDLError("%s cannot have %s argument" %
++- ("setter" if setter else "creator",
++- "optional" if arguments[0].optional else "variadic"),
+++ (("creator", "setter")[setter], ("variadic", "optional")[arguments[0].optional]),
++ [arguments[0].location])
++ if arguments[1].optional or arguments[1].variadic:
++ raise WebIDLError("%s cannot have %s argument" %
++- ("setter" if setter else "creator",
++- "optional" if arguments[1].optional else "variadic"),
+++ (("creator", "setter")[setter], ("variadic", "optional")[arguments[1].optional]),
++ [arguments[1].location])
++
++ if stringifier:
++@@ -4264,15 +4290,21 @@ class Parser(Tokenizer):
++ [self.getLocation(p, 2)])
++
++ location = BuiltinLocation("<auto-generated-identifier>")
+++ first_parm = ""
+++ if specialType == IDLMethod.NamedOrIndexed.Named:
+++ first_parm = "named"
+++ elif specialType == IDLMethod.NamedOrIndexed.Indexed:
+++ first_parm = "indexed"
+++
++ identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" %
++- ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \
++- "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "",
++- "getter" if getter else "",
++- "setter" if setter else "",
++- "deleter" if deleter else "",
++- "creator" if creator else "",
++- "legacycaller" if legacycaller else "",
++- "stringifier" if stringifier else ""), allowDoubleUnderscore=True)
+++ (first_parm,
+++ ("", "getter")[getter],
+++ ("", "setter")[setter],
+++ ("", "deleter")[deleter],
+++ ("", "creator")[creator],
+++ ("", "legacycaller")[legacycaller],
+++ ("", "stringifier")[stringifier]),
+++ allowDoubleUnderscore=True)
++
++ method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments,
++ static=static, getter=getter, setter=setter, creator=creator,
++@@ -4391,7 +4423,10 @@ class Parser(Tokenizer):
++ """
++ ArgumentList : Argument Arguments
++ """
++- p[0] = [p[1]] if p[1] else []
+++ if p[1]:
+++ p[0] = [p[1]]
+++ else:
+++ p[0] = []
++ p[0].extend(p[2])
++
++ def p_ArgumentListEmpty(self, p):
++@@ -4404,7 +4439,10 @@ class Parser(Tokenizer):
++ """
++ Arguments : COMMA Argument Arguments
++ """
++- p[0] = [p[2]] if p[2] else []
+++ if p[2]:
+++ p[0] = [p[2]]
+++ else:
+++ p[0] = []
++ p[0].extend(p[3])
++
++ def p_ArgumentsEmpty(self, p):
++@@ -4539,7 +4577,10 @@ class Parser(Tokenizer):
++ """
++ ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes
++ """
++- p[0] = [p[2]] if p[2] else []
+++ if p[2]:
+++ p[0] = [p[2]]
+++ else:
+++ p[0] = []
++ p[0].extend(p[3])
++
++ def p_ExtendedAttributesEmpty(self, p):
++@@ -5036,10 +5077,8 @@ class Parser(Tokenizer):
++ # First, finish all the IDLImplementsStatements. In particular, we
++ # have to make sure we do those before we do the IDLInterfaces.
++ # XXX khuey hates this bit and wants to nuke it from orbit.
++- implementsStatements = [ p for p in self._productions if
++- isinstance(p, IDLImplementsStatement)]
++- otherStatements = [ p for p in self._productions if
++- not isinstance(p, IDLImplementsStatement)]
+++ implementsStatements = [ p for p in self._productions if isinstance(p, IDLImplementsStatement)]
+++ otherStatements = [ p for p in self._productions if not isinstance(p, IDLImplementsStatement)]
++ for production in implementsStatements:
++ production.finish(self.globalScope())
++ for production in otherStatements:
++diff -up comm-esr31/mozilla/dom/imptests/importTestsuite.py.python3 comm-esr31/mozilla/dom/imptests/importTestsuite.py
++--- comm-esr31/mozilla/dom/imptests/importTestsuite.py.python3 2014-07-17 18:05:15.000000000 -0600
+++++ comm-esr31/mozilla/dom/imptests/importTestsuite.py 2014-10-24 11:41:35.453880252 -0600
++@@ -10,7 +10,11 @@ Note: removes both source and destinatio
++ use with outstanding changes in either directory.
++ """
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import shutil
++@@ -50,7 +54,8 @@ def getData(confFile):
++ iden = ""
++ directories = []
++ try:
++- with open(confFile, 'r') as fp:
+++ fp = open(confFile, 'r')
+++ if 1:
++ first = True
++ for line in fp:
++ if first:
++@@ -58,6 +63,7 @@ def getData(confFile):
++ first = False
++ else:
++ directories.append(line.strip())
+++ fp.close()
++ finally:
++ return vcs, url, iden, directories
++
++@@ -129,16 +135,20 @@ def printBuildFiles(dest, directories):
++ all_support |= set('%s/%s' % (d['path'], p) for p in d['supportfiles'])
++
++ if d["reftests"]:
++- with open(path + "/reftest.list", "w") as fh:
+++ fh = open(path + "/reftest.list", "w")
+++ if 1:
++ result = writeBuildFiles.substReftestList("importTestsuite.py",
++ d["reftests"])
++ fh.write(result)
++
+++ fh.close()
++ manifest_path = dest + '/mochitest.ini'
++- with open(manifest_path, 'w') as fh:
+++ fh = open(manifest_path, 'w')
+++ if 1:
++ result = writeBuildFiles.substManifest('importTestsuite.py',
++ all_mochitests, all_support)
++ fh.write(result)
+++ fh.close()
++ subprocess.check_call(["hg", "add", manifest_path])
++
++ def hgadd(dest, directories):
++@@ -176,7 +186,7 @@ def importRepo(confFile):
++ hgadd(dest, directories)
++ print("Removing %s again..." % hgdest)
++ subprocess.check_call(["rm", "-rf", hgdest])
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ print(e.returncode)
++ finally:
++ print("Done")
++diff -up comm-esr31/mozilla/dom/imptests/parseFailures.py.python3 comm-esr31/mozilla/dom/imptests/parseFailures.py
++--- comm-esr31/mozilla/dom/imptests/parseFailures.py.python3 2014-07-17 18:05:15.000000000 -0600
+++++ comm-esr31/mozilla/dom/imptests/parseFailures.py 2014-10-24 11:41:35.454880248 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import collections
++ import json
++@@ -59,11 +63,13 @@ def writeFiles(files):
++ pathmap.setdefault(dirp, []).append(leaf)
++
++ for k, v in pathmap.items():
++- with open(k + '/mochitest.ini', 'w') as fh:
+++ fh = open(k + '/mochitest.ini', 'w')
+++ if 1:
++ result = writeBuildFiles.substManifest('parseFailures.py', v, [])
++ fh.write(result)
++
++
+++ fh.close()
++ def main(logPath):
++ fp = open(logPath, 'rb')
++ lines = extractLines(fp)
++diff -up comm-esr31/mozilla/dom/imptests/updateTestharness.py.python3 comm-esr31/mozilla/dom/imptests/updateTestharness.py
++--- comm-esr31/mozilla/dom/imptests/updateTestharness.py.python3 2014-07-17 18:05:15.000000000 -0600
+++++ comm-esr31/mozilla/dom/imptests/updateTestharness.py 2014-10-24 11:41:35.454880248 -0600
++@@ -3,7 +3,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import subprocess
++
++@@ -18,7 +18,11 @@ subprocess.check_call(["git", "clone", r
++ subprocess.check_call(["git", "submodule", "init"], cwd=dest)
++ subprocess.check_call(["git", "submodule", "update"], cwd=dest)
++ for f in files:
++- path = f["d"] if "d" in f else f["f"]
+++ path = None
+++ if "d" in f:
+++ path = f["d"]
+++ else:
+++ path = f["f"]
++ subprocess.check_call(["cp", "%s/%s" % (dest, path), f["f"]])
++ subprocess.check_call(["hg", "add", f["f"]])
++ subprocess.check_call(["rm", "-rf", dest])
++diff -up comm-esr31/mozilla/dom/imptests/writeBuildFiles.py.python3 comm-esr31/mozilla/dom/imptests/writeBuildFiles.py
++--- comm-esr31/mozilla/dom/imptests/writeBuildFiles.py.python3 2014-07-17 18:05:15.000000000 -0600
+++++ comm-esr31/mozilla/dom/imptests/writeBuildFiles.py 2014-10-24 11:41:35.454880248 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import string
++
++diff -up comm-esr31/mozilla/gfx/gl/GLParseRegistryXML.py.python3 comm-esr31/mozilla/gfx/gl/GLParseRegistryXML.py
++--- comm-esr31/mozilla/gfx/gl/GLParseRegistryXML.py.python3 2014-07-17 18:05:20.000000000 -0600
+++++ comm-esr31/mozilla/gfx/gl/GLParseRegistryXML.py 2014-10-24 11:41:35.454880248 -0600
++@@ -181,7 +181,8 @@ class GLDatabase:
++
++
++ def exportConsts(self, path):
++- with open(getScriptDir() + path,'w') as f:
+++ f = open(getScriptDir() + path,'w')
+++ if 1:
++
++ headerFile = GLConstHeader(f)
++ headerFile.formatFileBegin()
++@@ -205,6 +206,7 @@ class GLDatabase:
++ headerFile.formatFileEnd()
++
++
+++ f.close()
++ glDatabase = GLDatabase()
++
++ success = glDatabase.loadXML('gl.xml')
++diff -up comm-esr31/mozilla/gfx/harfbuzz/src/gen-arabic-table.py.python3 comm-esr31/mozilla/gfx/harfbuzz/src/gen-arabic-table.py
++--- comm-esr31/mozilla/gfx/harfbuzz/src/gen-arabic-table.py.python3 2014-07-17 18:05:20.000000000 -0600
+++++ comm-esr31/mozilla/gfx/harfbuzz/src/gen-arabic-table.py 2014-10-24 11:41:35.454880248 -0600
++@@ -122,10 +122,14 @@ def print_shaping_table(f):
++ keys = shapes.keys ()
++ min_u, max_u = min (keys), max (keys)
++ for u in range (min_u, max_u + 1):
++- s = [shapes[u][shape] if u in shapes and shape in shapes[u] else 0
+++ s = None
+++if u in shapes and shape in shapes[u]:
+++ s = [shapes[u][shape]
+++else:
+++ s = 0
++ for shape in ['initial', 'medial', 'final', 'isolated']]
++ value = ', '.join ("0x%04X" % c for c in s)
++- print " {%s}, /* U+%04X %s */" % (value, u, names[u] if u in names else "")
+++ print " {%s}, /* U+%04X %s */" % (value, u, names[u]u in names = (""), )[]
++
++ print "};"
++ print
++diff -up comm-esr31/mozilla/gfx/layers/genTables.py.python3 comm-esr31/mozilla/gfx/layers/genTables.py
++--- comm-esr31/mozilla/gfx/layers/genTables.py.python3 2014-07-17 18:05:20.000000000 -0600
+++++ comm-esr31/mozilla/gfx/layers/genTables.py 2014-10-24 11:41:35.455880244 -0600
++@@ -3,10 +3,12 @@
++ def table_generator(f):
++ return ",\n".join([", ".join(["0x%2.2x" % h for h in [f(i) for i in range(r,r+16)]]) for r in range(0, 65536, 16)])
++
++-with open("PremultiplyTables.h", "w") as f:
+++f = open("PremultiplyTables.h", "w")
+++if 1:
++ f.write("const uint8_t PremultiplyTable[256*256] = {\n");
++ f.write(table_generator(lambda i: ((i / 256) * (i % 256) + 254) / 255) + "\n")
++ f.write("};\n");
++ f.write("const uint8_t UnpremultiplyTable[256*256] = {\n");
++- f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
+++ f.write(table_generator(lambda i: (i % 256) * 255 / ((255, i / 256)[(i / 256) > 0]) % 256) + "\n")
++ f.write("};\n");
+++f.close()
++diff -up comm-esr31/mozilla/gfx/thebes/gencjkcisvs.py.python3 comm-esr31/mozilla/gfx/thebes/gencjkcisvs.py
++--- comm-esr31/mozilla/gfx/thebes/gencjkcisvs.py.python3 2014-07-17 18:05:21.000000000 -0600
+++++ comm-esr31/mozilla/gfx/thebes/gencjkcisvs.py 2014-10-24 11:41:35.455880244 -0600
++@@ -6,7 +6,11 @@ import os.path
++ import re
++ import sys
++
++-f = open(sys.argv[1] if len(sys.argv) > 1 else 'StandardizedVariants.txt')
+++f = None
+++if len(sys.argv) > 1:
+++ f = open(sys.argv[1]
+++else:
+++ f = 'StandardizedVariants.txt')
++
++ line = f.readline()
++ m = re.compile('^# (StandardizedVariants(-\d+(\.\d+)*)?\.txt)').search(line)
++@@ -37,7 +41,7 @@ for (k, mappings) in sorted(vsdict.items
++ offsets.append(length)
++ length += 4 + 5 * len(mappings)
++
++-f = open(sys.argv[2] if len(sys.argv) > 2 else 'CJKCompatSVS.cpp', 'wb')
+++f = open(('CJKCompatSVS.cpp', sys.argv[2])[len(sys.argv) > 2], 'wb')
++ f.write("""// Generated by %s. Do not edit.
++
++ #include <stdint.h>
++diff -up comm-esr31/mozilla/gfx/thebes/genTables.py.python3 comm-esr31/mozilla/gfx/thebes/genTables.py
++--- comm-esr31/mozilla/gfx/thebes/genTables.py.python3 2014-07-17 18:05:21.000000000 -0600
+++++ comm-esr31/mozilla/gfx/thebes/genTables.py 2014-10-24 11:41:35.455880244 -0600
++@@ -3,10 +3,14 @@
++ def table_generator(f):
++ return ",\n".join([", ".join(["0x%2.2x" % h for h in [f(i) for i in range(r,r+16)]]) for r in range(0, 65536, 16)])
++
++-with open("DeprecatedPremultiplyTables.h", "w") as f:
+++f = open("DeprecatedPremultiplyTables.h", "w")
+++if 1:
++ f.write("const uint8_t gfxUtils::sPremultiplyTable[256*256] = {\n");
++ f.write(table_generator(lambda i: ((i / 256) * (i % 256) + 254) / 255) + "\n")
++ f.write("};\n");
++ f.write("const uint8_t gfxUtils::sUnpremultiplyTable[256*256] = {\n");
++- f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
+++ #f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
+++ #f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256, 255)[(i / 256) > 0]) % 256) + "\n")
+++ f.write(table_generator(lambda i: (i % 256) * 255 / ((255, i / 256)[(i / 256) > 0]) % 256) + "\n")
++ f.write("};\n");
+++f.close()
++diff -up comm-esr31/mozilla/ipc/chromium/src/third_party/libevent/event_rpcgen.py.python3 comm-esr31/mozilla/ipc/chromium/src/third_party/libevent/event_rpcgen.py
++--- comm-esr31/mozilla/ipc/chromium/src/third_party/libevent/event_rpcgen.py.python3 2014-07-17 18:05:24.000000000 -0600
+++++ comm-esr31/mozilla/ipc/chromium/src/third_party/libevent/event_rpcgen.py 2014-10-24 11:41:35.455880244 -0600
++@@ -1628,8 +1628,7 @@ class Usage(RpcGenError):
++
++ class CommandLine:
++ def __init__(self, argv):
++- """Initialize a command-line to launch event_rpcgen, as if
++- from a command-line with CommandLine(sys.argv). If you're
+++ """Initialize a command-line to launch event_rpcgen, as if from a command-line with CommandLine(sys.argv). If you're
++ calling this directly, remember to provide a dummy value
++ for sys.argv[0]
++ """
++diff -up comm-esr31/mozilla/ipc/ipdl/ipdl/__init__.py.python3 comm-esr31/mozilla/ipc/ipdl/ipdl/__init__.py
++--- comm-esr31/mozilla/ipc/ipdl/ipdl/__init__.py.python3 2014-07-17 18:05:24.000000000 -0600
+++++ comm-esr31/mozilla/ipc/ipdl/ipdl/__init__.py 2014-10-24 11:41:35.456880240 -0600
++@@ -30,8 +30,7 @@ def parse(specstring, filename='/stdin',
++
++
++ def typecheck(ast, errout=sys.stderr):
++- '''Return True iff |ast| is well typed. Print errors to |errout| if
++- it is not.'''
+++ '''Return True iff |ast| is well typed. Print errors to |errout| if it is not.'''
++ return TypeCheck().check(ast, errout)
++
++
++diff -up comm-esr31/mozilla/ipc/ipdl/ipdl/lower.py.python3 comm-esr31/mozilla/ipc/ipdl/ipdl/lower.py
++--- comm-esr31/mozilla/ipc/ipdl/ipdl/lower.py.python3 2014-07-17 18:05:24.000000000 -0600
+++++ comm-esr31/mozilla/ipc/ipdl/ipdl/lower.py 2014-10-24 11:41:35.457880235 -0600
++@@ -3876,7 +3876,7 @@ class _GenerateProtocolActorCode(ipdl.as
++
++ registerstmt = StmtExpr(ExprCall(p.registerIDMethod(),
++ args=[actorvar, _actorId(actorvar)]))
++- # Implement if (actor id > 0) then Register() else RegisterID()
+++ # Implement(actor id > 0) then Register() = (RegisterID(), )[]
++ if manageeipdltype in inoutCtorTypes:
++ registerif = StmtIf(ExprBinary(_actorId(actorvar),
++ '>',
++@@ -4684,7 +4684,7 @@ class _GenerateProtocolActorCode(ipdl.as
++ ct = c.bareType()
++ readcase.addstmts([
++ StmtDecl(Decl(ct, tmpvar.name),
++- init=c.defaultValue() if ct.ptr else None),
+++ init=(None, c.defaultValue())[ct.ptr]),
++ StmtExpr(ExprAssn(ExprDeref(var), tmpvar)),
++ StmtReturn(self.read(
++ c.ipdltype,
++@@ -5363,7 +5363,7 @@ class _GenerateProtocolActorCode(ipdl.as
++ ExprSelect(msgptr, '->', 'Log'),
++ args=[ ExprLiteral.String('['+ actorname +'] '+ pfx),
++ self.protocol.callOtherProcess(actor),
++- ExprLiteral.TRUE if receiving else ExprLiteral.FALSE ])) ])
+++ (ExprLiteral.FALSE, ExprLiteral.TRUE)[receiving] ])) ])
++
++ def profilerLabel(self, tag, msgname):
++ return StmtExpr(ExprCall(ExprVar('PROFILER_LABEL'),
++@@ -5393,7 +5393,11 @@ class _GenerateProtocolActorCode(ipdl.as
++ action = ExprVar('Trigger::Recv')
++ else: assert 0 and 'unknown combo %s/%s'% (self.side, direction)
++
++- msgid = md.pqMsgId() if not reply else md.pqReplyId()
+++ msgid = None
+++ if not reply:
+++ msgid = md.pqMsgId()
+++ else:
+++ msgid = md.pqReplyId()
++ ifbad = StmtIf(ExprNot(
++ ExprCall(
++ ExprVar(self.protocol.name +'::Transition'),
++diff -up comm-esr31/mozilla/js/src/builtin/embedjs.py.python3 comm-esr31/mozilla/js/src/builtin/embedjs.py
++--- comm-esr31/mozilla/js/src/builtin/embedjs.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/builtin/embedjs.py 2014-10-24 11:41:35.457880235 -0600
++@@ -36,7 +36,7 @@
++ #
++ # It uses the C preprocessor to process its inputs.
++
++-from __future__ import with_statement
+++
++ import re, sys, os, fileinput, subprocess
++ import shlex
++ from optparse import OptionParser
++@@ -81,8 +81,10 @@ def embed(cpp, msgs, sources, c_out, js_
++ # Clang seems to complain and not output anything if the extension of the
++ # input is not something it recognizes, so just fake a .h here.
++ tmp = 'selfhosted.js.h'
++- with open(tmp, 'wb') as output:
+++ output = open(tmp, 'wb')
+++ if 1:
++ output.write('\n'.join([msgs] + ['#include "%(s)s"' % { 's': source } for source in sources]))
+++ output.close()
++ cmdline = cpp + ['-D%(k)s=%(v)s' % { 'k': k, 'v': env[k] } for k in env] + [tmp]
++ p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
++ processed = ''
++@@ -90,9 +92,12 @@ def embed(cpp, msgs, sources, c_out, js_
++ if not line.startswith('#'):
++ processed += line
++ os.remove(tmp)
++- with open(js_out, 'w') as output:
+++ output = open(js_out, 'w')
+++ if 1:
++ output.write(processed)
++- with open(c_out, 'w') as output:
+++ output.close()
+++ output = open(c_out, 'w')
+++ if 1:
++ if 'USE_ZLIB' in env:
++ import zlib
++ compressed = zlib.compress(processed)
++@@ -114,12 +119,15 @@ def embed(cpp, msgs, sources, c_out, js_
++ 'raw_total_length': len(processed)
++ })
++
+++ output.close()
++ def process_msgs(cpp, msgs):
++ # Clang seems to complain and not output anything if the extension of the
++ # input is not something it recognizes, so just fake a .h here.
++ tmp = 'selfhosted.msg.h'
++- with open(tmp, 'wb') as output:
+++ output = open(tmp, 'wb')
+++ if 1:
++ output.write("""\
+++ output.close()
++ #define hash #
++ #define id(x) x
++ #define hashify(x) id(hash)x
++diff -up comm-esr31/mozilla/js/src/configure.python3 comm-esr31/mozilla/js/src/configure
++--- comm-esr31/mozilla/js/src/configure.python3 2014-07-17 18:06:19.000000000 -0600
+++++ comm-esr31/mozilla/js/src/configure 2014-10-24 11:41:35.459880227 -0600
++@@ -16270,7 +16270,8 @@ rm confdefs.pytmp confdefs.h
++ cat >> $CONFIG_STATUS <<\EOF
++ ] ]
++
++-substs = [(name[1:-1], value[1:-1] if isinstance(value, types.StringTypes) else value) for name, value in [
+++substs = []
+++mylist = [
++ EOF
++
++ sed 's/$/,/' >> $CONFIG_STATUS <<EOF
++@@ -16578,7 +16579,12 @@ for ac_subst_arg in $_subconfigure_ac_su
++ done
++
++ cat >> $CONFIG_STATUS <<\EOF
++-] ]
+++]
+++for name, value in mylist:
+++ if isinstance(value, types.StringTypes):
+++ substs.append( (name[1:-1], value[1:-1]) )
+++ else:
+++ substs.append( (name[1:-1], value) )
++
++ non_global_defines = [
++ EOF
++diff -up comm-esr31/mozilla/js/src/devtools/rootAnalysis/analyze.py.python3 comm-esr31/mozilla/js/src/devtools/rootAnalysis/analyze.py
++--- comm-esr31/mozilla/js/src/devtools/rootAnalysis/analyze.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/devtools/rootAnalysis/analyze.py 2014-10-24 11:41:35.459880227 -0600
++@@ -89,11 +89,13 @@ def generate_hazards(config, outfilename
++ if final_status:
++ raise subprocess.CalledProcessError(final_status, 'analyzeRoots.js')
++
++- with open(outfilename, 'w') as output:
+++ output = open(outfilename, 'w')
+++ if 1:
++ command = ['cat'] + [ 'rootingHazards.%s' % (i+1,) for i in range(config['jobs']) ]
++ print_command(command, outfile=outfilename)
++ subprocess.call(command, stdout=output)
++
+++ output.close()
++ JOBS = { 'dbs':
++ (('%(ANALYSIS_SCRIPTDIR)s/run_complete',
++ '--foreground',
++@@ -171,8 +173,10 @@ def run_job(name, config):
++ if stdout_filename is None:
++ subprocess.check_call(command, env=env(config))
++ else:
++- with open(stdout_filename, 'w') as output:
+++ output = open(stdout_filename, 'w')
+++ if 1:
++ subprocess.check_call(command, stdout=output, env=env(config))
+++ output.close()
++ for (temp, final) in temp_map.items():
++ try:
++ os.rename(temp, final)
++diff -up comm-esr31/mozilla/js/src/devtools/rootAnalysis/explain.py.python3 comm-esr31/mozilla/js/src/devtools/rootAnalysis/explain.py
++--- comm-esr31/mozilla/js/src/devtools/rootAnalysis/explain.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/devtools/rootAnalysis/explain.py 2014-10-24 11:41:35.460880223 -0600
++@@ -65,7 +65,8 @@ try:
++ else:
++ hazardousGCFunctions[current_gcFunction][-1] += line
++
++- with open(args.gcFunctions) as gcFunctions:
+++ gcFunctions = open(args.gcFunctions)
+++ if 1:
++ gcExplanations = {} # gcFunction => stack showing why it can GC
++
++ current_func = None
++@@ -91,7 +92,8 @@ try:
++ else:
++ print >>hazards, gcHazards[index]
++
++-except IOError as e:
+++ gcFunctions.close()
+++except IOError, e:
++ print 'Failed: %s' % str(e)
++
++ print("Wrote %s" % args.hazards)
++diff -up comm-esr31/mozilla/js/src/gdb/lib-for-tests/catcher.py.python3 comm-esr31/mozilla/js/src/gdb/lib-for-tests/catcher.py
++--- comm-esr31/mozilla/js/src/gdb/lib-for-tests/catcher.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/lib-for-tests/catcher.py 2014-10-24 11:41:35.460880223 -0600
++@@ -16,7 +16,7 @@ try:
++ # testlibdir is set on the GDB command line, via:
++ # --eval-command python testlibdir=...
++ execfile(os.path.join(testlibdir, 'prolog.py'))
++-except Exception as err:
+++except Exception, err:
++ sys.stderr.write('Error running GDB prologue:\n')
++ traceback.print_exc()
++ sys.exit(1)
++diff -up comm-esr31/mozilla/js/src/gdb/lib-for-tests/prolog.py.python3 comm-esr31/mozilla/js/src/gdb/lib-for-tests/prolog.py
++--- comm-esr31/mozilla/js/src/gdb/lib-for-tests/prolog.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/lib-for-tests/prolog.py 2014-10-24 11:41:35.460880223 -0600
++@@ -65,7 +65,7 @@ try:
++ # testscript is set on the GDB command line, via:
++ # --eval-command python testscript=...
++ execfile(testscript)
++-except AssertionError as err:
+++except AssertionError, err:
++ sys.stderr.write('\nAssertion traceback:\n')
++ (t, v, tb) = sys.exc_info()
++ traceback.print_tb(tb)
++diff -up comm-esr31/mozilla/js/src/gdb/mozilla/JSObject.py.python3 comm-esr31/mozilla/js/src/gdb/mozilla/JSObject.py
++--- comm-esr31/mozilla/js/src/gdb/mozilla/JSObject.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/mozilla/JSObject.py 2014-10-24 11:41:35.460880223 -0600
++@@ -46,10 +46,13 @@ class JSObjectPtrOrRef(prettyprinters.Po
++ function = function.address
++ function = function.cast(self.otc.func_ptr_type)
++ atom = deref(function['atom_'])
++- name = str(atom) if atom else '<unnamed>'
+++ name = None
+++ if atom:
+++ name = str(atom)
+++ else:
+++ name = '<unnamed>'
++ return '[object %s%s]%s' % (class_name,
++- ' ' + name if name else '',
++- ' delegate' if is_delegate else '')
+++ ('', ' ' + name)[name], ('', ' delegate')[is_delegate])
++
++ @ref_pretty_printer('JSObject')
++ def JSObjectRef(value, cache): return JSObjectPtrOrRef(value, cache)
++diff -up comm-esr31/mozilla/js/src/gdb/mozilla/jsval.py.python3 comm-esr31/mozilla/js/src/gdb/mozilla/jsval.py
++--- comm-esr31/mozilla/js/src/gdb/mozilla/jsval.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/mozilla/jsval.py 2014-10-24 11:41:35.460880223 -0600
++@@ -171,7 +171,11 @@ class jsvalTypeCache(object):
++ for (k,v) in d.items(): self.magic_names[v] = k
++
++ # Choose an unboxing scheme for this architecture.
++- self.boxer = Punbox if cache.void_ptr_t.sizeof == 8 else Nunbox
+++ self.boxer = None
+++ if cache.void_ptr_t.sizeof == 8:
+++ self.boxer = Punbox
+++ else:
+++ self.boxer = Nunbox
++
++ @pretty_printer('jsval_layout')
++ class jsval_layout(object):
++@@ -194,7 +198,7 @@ class jsval_layout(object):
++ elif tag == self.jtc.UNDEFINED:
++ return 'JSVAL_VOID'
++ elif tag == self.jtc.BOOLEAN:
++- return 'JSVAL_TRUE' if self.box.as_uint32() else 'JSVAL_FALSE'
+++ return ('JSVAL_FALSE', 'JSVAL_TRUE')[self.box.as_uint32()]
++ elif tag == self.jtc.MAGIC:
++ value = self.box.as_uint32()
++ if 0 <= value and value < len(self.jtc.magic_names):
++diff -up comm-esr31/mozilla/js/src/gdb/mozilla/prettyprinters.py.python3 comm-esr31/mozilla/js/src/gdb/mozilla/prettyprinters.py
++--- comm-esr31/mozilla/js/src/gdb/mozilla/prettyprinters.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/mozilla/prettyprinters.py 2014-10-24 11:41:35.460880223 -0600
++@@ -335,7 +335,7 @@ class Pointer(object):
++ assert not "mozilla.prettyprinters.Pointer applied to bad value type"
++ try:
++ summary = self.summary()
++- except gdb.MemoryError as r:
+++ except gdb.MemoryError, r:
++ summary = str(r)
++ v = '(%s) %s %s' % (self.value.type, address, summary)
++ return v
++diff -up comm-esr31/mozilla/js/src/gdb/run-tests.py.python3 comm-esr31/mozilla/js/src/gdb/run-tests.py
++--- comm-esr31/mozilla/js/src/gdb/run-tests.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/run-tests.py 2014-10-24 11:41:35.461880219 -0600
++@@ -110,20 +110,24 @@ class Summary(object):
++
++ if OPTIONS.worklist:
++ try:
++- with open(OPTIONS.worklist) as out:
+++ out = open(OPTIONS.worklist)
+++ if 1:
++ for test in self.failures:
++ out.write(test.name + '\n')
++- except IOError as err:
+++ out.__exit__(0, 0, 0)
+++ except IOError, err:
++ sys.stderr.write("Error writing worklist file '%s': %s"
++ % (OPTIONS.worklist, err))
++ sys.exit(1)
++
++ if OPTIONS.write_failures:
++ try:
++- with open(OPTIONS.write_failures) as out:
+++ out = open(OPTIONS.write_failures).__enter__()
+++ if 1:
++ for test in self.failures:
++ test.show(out)
++- except IOError as err:
+++ out.close()
+++ except IOError, err:
++ sys.stderr.write("Error writing worklist file '%s': %s"
++ % (OPTIONS.write_failures, err))
++ sys.exit(1)
++@@ -288,9 +292,11 @@ def main(argv):
++ test_set.update(find_tests(OPTIONS.testdir, arg))
++ if OPTIONS.worklist:
++ try:
++- with open(OPTIONS.worklist) as f:
+++ f = open(OPTIONS.worklist)
+++ if 1:
++ for line in f:
++ test_set.update(os.path.join(test_dir, line.strip('\n')))
+++ f.__exit__(0, 0, 0)
++ except IOError:
++ # With worklist, a missing file means to start the process with
++ # the complete list of tests.
++@@ -299,10 +305,12 @@ def main(argv):
++ test_set = set(find_tests(OPTIONS.testdir))
++ if OPTIONS.read_tests:
++ try:
++- with open(OPTIONS.read_tests) as f:
+++ f = open(OPTIONS.read_tests).__enter__()
+++ if 1:
++ for line in f:
++ test_set.update(os.path.join(test_dir, line.strip('\n')))
++- except IOError as err:
+++ f.close()
+++ except IOError, err:
++ sys.stderr.write("Error trying to read test file '%s': %s\n"
++ % (OPTIONS.read_tests, err))
++ sys.exit(1)
++@@ -329,7 +337,7 @@ def main(argv):
++ # directory tree.
++ try:
++ build_test_exec(OPTIONS.builddir)
++- except subprocess.CalledProcessError as err:
+++ except subprocess.CalledProcessError, err:
++ sys.stderr.write("Error building test executable: %s\n" % (err,))
++ sys.exit(1)
++
++@@ -338,7 +346,7 @@ def main(argv):
++ summary.start()
++ run_tests(test_list, summary)
++ summary.finish()
++- except OSError as err:
+++ except OSError, err:
++ sys.stderr.write("Error running tests: %s\n" % (err,))
++ sys.exit(1)
++
++diff -up comm-esr31/mozilla/js/src/gdb/taskpool.py.python3 comm-esr31/mozilla/js/src/gdb/taskpool.py
++--- comm-esr31/mozilla/js/src/gdb/taskpool.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/gdb/taskpool.py 2014-10-24 11:41:35.461880219 -0600
++@@ -75,7 +75,8 @@ class TaskPool(object):
++ def run_all(self):
++ # The currently running tasks: a set of Task instances.
++ running = set()
++- with open(os.devnull, 'r') as devnull:
+++ devnull = open(os.devnull, 'r')
+++ if 1:
++ while True:
++ while len(running) < self.job_limit and self.next_pending:
++ t = self.next_pending
++@@ -158,6 +159,7 @@ class TaskPool(object):
++ # Remove the finished tasks from the running set. (Do this here
++ # to avoid mutating the set while iterating over it.)
++ running -= finished
+++ devnull.close()
++ return None
++
++ def get_cpu_count():
++diff -up comm-esr31/mozilla/js/src/jit-test/jit_test.py.python3 comm-esr31/mozilla/js/src/jit-test/jit_test.py
++--- comm-esr31/mozilla/js/src/jit-test/jit_test.py.python3 2014-07-17 18:05:25.000000000 -0600
+++++ comm-esr31/mozilla/js/src/jit-test/jit_test.py 2014-10-24 11:41:35.461880219 -0600
++@@ -109,8 +109,7 @@ def main(argv):
++ test_args = args[1:]
++
++ if jittests.stdio_might_be_broken():
++- # Prefer erring on the side of caution and not using stdio if
++- # it might be broken on this platform. The file-redirect
+++ # Prefer erring on the side of caution and not using stdio if # it might be broken on this platform. The file-redirect
++ # fallback should work on any platform, so at worst by
++ # guessing wrong we might have slowed down the tests a bit.
++ #
++diff -up comm-esr31/mozilla/js/src/tests/jstests.py.python3 comm-esr31/mozilla/js/src/tests/jstests.py
++--- comm-esr31/mozilla/js/src/tests/jstests.py.python3 2014-07-17 18:05:28.000000000 -0600
+++++ comm-esr31/mozilla/js/src/tests/jstests.py 2014-10-24 11:41:35.461880219 -0600
++@@ -151,7 +151,11 @@ def parse_args():
++ op.error("--valgrind and --debug are mutually exclusive.")
++
++ # Fill the debugger field, as needed.
++- prefix = options.debugger.split() if options.debug else []
+++ prefix = None
+++ if options.debug:
+++ prefix = options.debugger.split()
+++ else:
+++ prefix = []
++ if options.valgrind:
++ prefix = ['valgrind'] + options.valgrind_args.split()
++ if os.uname()[0] == 'Darwin':
++diff -up comm-esr31/mozilla/js/src/tests/lib/manifest.py.python3 comm-esr31/mozilla/js/src/tests/lib/manifest.py
++--- comm-esr31/mozilla/js/src/tests/lib/manifest.py.python3 2014-07-17 18:05:28.000000000 -0600
+++++ comm-esr31/mozilla/js/src/tests/lib/manifest.py 2014-10-24 11:41:35.462880214 -0600
++@@ -286,7 +286,8 @@ def _parse_external_manifest(filename, r
++ """
++ entries = []
++
++- with open(filename, 'r') as fp:
+++ fp = open(filename, 'r')
+++ if 1:
++ manifest_re = re.compile(r'^\s*(.*)\s+(include|script)\s+(\S+)$')
++ for line in fp:
++ line, _, comment = line.partition('#')
++@@ -309,6 +310,7 @@ def _parse_external_manifest(filename, r
++
++ entries.append({'path': path, 'terms': matches.group(1), 'comment': comment.strip()})
++
+++ fp.close()
++ # if one directory name is a prefix of another, we want the shorter one first
++ entries.sort(key=lambda x: x["path"])
++ return entries
++diff -up comm-esr31/mozilla/js/src/tests/lib/progressbar.py.python3 comm-esr31/mozilla/js/src/tests/lib/progressbar.py
++--- comm-esr31/mozilla/js/src/tests/lib/progressbar.py.python3 2014-07-17 18:05:28.000000000 -0600
+++++ comm-esr31/mozilla/js/src/tests/lib/progressbar.py 2014-10-24 11:41:35.462880214 -0600
++@@ -79,7 +79,11 @@ class ProgressBar(object):
++ self.update(*self.prior)
++
++ def finish(self, complete=True):
++- final_count = self.limit if complete else self.prior[0]
+++ final_count = None
+++ if complete:
+++ final_count = self.limit
+++ else:
+++ final_count = self.prior[0]
++ self.update(final_count, self.prior[1])
++ sys.stdout.write('\n')
++
++@@ -96,8 +100,7 @@ class ProgressBar(object):
++ @staticmethod
++ def conservative_isatty():
++ """
++- Prefer erring on the side of caution and not using terminal commands if
++- the current output stream may be a file. We explicitly check for the
+++ Prefer erring on the side of caution and not using terminal commands if the current output stream may be a file. We explicitly check for the
++ Android platform because terminal commands work poorly over ADB's
++ redirection.
++ """
++diff -up comm-esr31/mozilla/js/src/tests/lib/results.py.python3 comm-esr31/mozilla/js/src/tests/lib/results.py
++--- comm-esr31/mozilla/js/src/tests/lib/results.py.python3 2014-07-17 18:05:28.000000000 -0600
+++++ comm-esr31/mozilla/js/src/tests/lib/results.py 2014-10-24 11:41:35.462880214 -0600
++@@ -167,7 +167,10 @@ class ResultsSink:
++
++ if dev_label:
++ def singular(label):
++- return "FIXED" if label == "FIXES" else label[:-1]
+++ if label == "FIXES":
+++ return "FIXED"
+++ else:
+++ return label[:-1]
++ self.pb.message("%s - %s" % (singular(dev_label), output.test.path))
++
++ self.pb.update(self.n, self.counts)
++@@ -216,7 +219,7 @@ class ResultsSink:
++ print >> failure_file, path
++ failure_file.close()
++
++- suffix = '' if completed else ' (partial run -- interrupted by user)'
+++ suffix = (' (partial run -- interrupted by user)', '')[completed]
++ if self.all_passed():
++ print 'PASS' + suffix
++ else:
++diff -up comm-esr31/mozilla/js/xpconnect/src/event_impl_gen.py.python3 comm-esr31/mozilla/js/xpconnect/src/event_impl_gen.py
++--- comm-esr31/mozilla/js/xpconnect/src/event_impl_gen.py.python3 2014-07-17 18:05:30.000000000 -0600
+++++ comm-esr31/mozilla/js/xpconnect/src/event_impl_gen.py 2014-10-24 11:41:35.462880214 -0600
++@@ -499,13 +499,13 @@ def toWebIDLType(attribute, inType=False
++ if attribute.type == "nsIVariant":
++ return "any";
++ if attribute.type == "nsISupports":
++- return "%s%s" % (attribute.type, "" if onlyInterface else "?")
+++ return "%s%s" % (attribute.type, ("?", "")[onlyInterface])
++ if attribute.type.count("nsIDOM"):
++- return "%s%s" % (attribute.type[6:], "" if onlyInterface else "?")
+++ return "%s%s" % (attribute.type[6:], ("?", "")[onlyInterface])
++ if attribute.type.count("nsI"):
++- return "%s%s" % (attribute.type[3:], "" if onlyInterface else "?")
+++ return "%s%s" % (attribute.type[3:], ("?", "")[onlyInterface])
++ if attribute.realtype.nativeType('in').endswith('*') or attribute.realtype.nativeType('in').count("nsAString"):
++- return "%s%s" % (attribute.type, "" if onlyInterface else "?")
+++ return "%s%s" % (attribute.type, ("?", "")[onlyInterface])
++ return attribute.type
++
++ def write_webidl(eventname, iface, fd, conf, idl):
++diff -up comm-esr31/mozilla/js/xpconnect/src/qsgen.py.python3 comm-esr31/mozilla/js/xpconnect/src/qsgen.py
++--- comm-esr31/mozilla/js/xpconnect/src/qsgen.py.python3 2014-07-17 18:05:30.000000000 -0600
+++++ comm-esr31/mozilla/js/xpconnect/src/qsgen.py 2014-10-24 11:41:35.463880210 -0600
++@@ -22,8 +22,8 @@
++ # case, everything that involves interpreting xptcall data (for example, the
++ # big methodInfo loops in XPCWrappedNative::CallMethod and the switch statement
++ # in XPCConert::JSData2Native) might as well happen at build time, since all
++-# the type information for any given member is already known. That's what this
++-# script does. It gets the information from IDL instead of XPT files. Apart
+++# the type i % ion for any given member is already known. That's what this
+++# script does. It gets the i % ion from IDL instead of XPT files. Apart
++ # from that, the code in this script is very similar to what you'll find in
++ # XPConnect itself. The advantage is that it runs once, at build time, not in
++ # tight loops at run time.
++@@ -233,7 +233,7 @@ def readConfigFile(filename, includePath
++ # Read the config file.
++ conf = Configuration(filename, includePath)
++
++- # Now read IDL files to connect the information in the config file to
+++ # Now read IDL files to connect the i % ion in the config file to
++ # actual XPCOM interfaces, methods, and attributes.
++ interfaces = []
++ interfacesByName = {}
++@@ -512,12 +512,12 @@ def writeArgumentUnboxing(f, i, name, ty
++ # passed in at all. In that case, point the MutableHandleValue at a
++ # dummy variable, and pass in a boolean saying that the argument
++ # wasn't passed (previously, this used a NULL ptr sentinel value.)
++- f.write(" JS::RootedValue {name}_dummy(cx);\n".format(name=name))
++- f.write(" JS::MutableHandleValue {name}_mhv({i} < argc ? args[{i}] : &{name}_dummy);\n".format(name=name, i=i))
++- f.write(" (void) {name}_mhv;\n".format(name=name, i=i))
+++ f.write(" JS::RootedValue %s_dummy(cx);\n" % name)
+++ f.write(" JS::MutableHandleValue %s_mhv(%d < argc ? args[%d] : &%s_dummy);\n" % (name, i, i, name))
+++ f.write(" (void) %s_mhv;\n" % (name))
++
++- argPtr = "{name}_mhv".format(name=name)
++- notPassed = "argc < {i}".format(i=i)
+++ argPtr = "%s_mhv" % name
+++ notPassed = "argc < %d" % i
++ else:
++ argVal = "args[%d]" % i
++ argPtr = "args[%d]" % i
++diff -up comm-esr31/mozilla/layout/tools/reftest/b2g_desktop.py.python3 comm-esr31/mozilla/layout/tools/reftest/b2g_desktop.py
++--- comm-esr31/mozilla/layout/tools/reftest/b2g_desktop.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/layout/tools/reftest/b2g_desktop.py 2014-10-24 11:41:35.463880210 -0600
++@@ -1,7 +1,11 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import json
++ import os
++diff -up comm-esr31/mozilla/layout/tools/reftest/mach_commands.py.python3 comm-esr31/mozilla/layout/tools/reftest/mach_commands.py
++--- comm-esr31/mozilla/layout/tools/reftest/mach_commands.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/layout/tools/reftest/mach_commands.py 2014-10-24 11:41:35.463880210 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import mozpack.path
++ import os
++@@ -142,15 +142,19 @@ class ReftestRunner(MozbuildObject):
++
++ # The imp module can spew warnings if the modules below have
++ # already been imported, ignore them.
++- with warnings.catch_warnings():
+++ warnings.catch_warnings().__enter__()
+++ if 1:
++ warnings.simplefilter('ignore')
++
++ import imp
++ path = os.path.join(self.reftest_dir, 'runreftestb2g.py')
++- with open(path, 'r') as fh:
+++ fh = open(path, 'r')
+++ if 1:
++ imp.load_module('reftest', fh, path, ('.py', 'r', imp.PY_SOURCE))
+++ fh.close()
++ import reftest
++
+++ warnings.catch_warnings().__exit__(0, 0, 0)
++ # Set up the reftest options.
++ parser = reftest.B2GOptions()
++ options, args = parser.parse_args([])
++diff -up comm-esr31/mozilla/layout/tools/reftest/runreftestb2g.py.python3 comm-esr31/mozilla/layout/tools/reftest/runreftestb2g.py
++--- comm-esr31/mozilla/layout/tools/reftest/runreftestb2g.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/layout/tools/reftest/runreftestb2g.py 2014-10-24 11:41:35.463880210 -0600
++@@ -400,9 +400,11 @@ class B2GRemoteReftest(RefTest):
++ config.set(section, 'Path', profilePath)
++
++ newProfilesIni = tempfile.mktemp()
++- with open(newProfilesIni, 'wb') as configfile:
+++ configfile = open(newProfilesIni, 'wb')
+++ if 1:
++ config.write(configfile)
++
+++ configfile.close()
++ self._devicemanager.pushFile(newProfilesIni, self.remoteProfilesIniPath)
++ try:
++ os.remove(newProfilesIni)
++diff -up comm-esr31/mozilla/layout/tools/reftest/runreftest.py.python3 comm-esr31/mozilla/layout/tools/reftest/runreftest.py
++--- comm-esr31/mozilla/layout/tools/reftest/runreftest.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/layout/tools/reftest/runreftest.py 2014-10-24 11:41:35.464880206 -0600
++@@ -57,14 +57,18 @@ class ReftestThread(threading.Thread):
++ self.summaryMatches[text] = None
++
++ def run(self):
++- with printLock:
+++ printLock.__enter__()
+++ if 1:
++ print "Starting thread with", self.cmdlineArgs
++ sys.stdout.flush()
+++ printLock.__exit__(0, 0, 0)
++ process = subprocess.Popen(self.cmdlineArgs, stdout=subprocess.PIPE)
++ for chunk in self.chunkForMergedOutput(process.stdout):
++- with printLock:
+++ printLock.__enter__()
+++ if 1:
++ print chunk,
++ sys.stdout.flush()
+++ printLock.__exit__(0, 0, 0)
++ self.retcode = process.wait()
++
++ def chunkForMergedOutput(self, logsource):
++@@ -301,9 +305,17 @@ class RefTest(object):
++ for (summaryObj, (text, categories)) in zip(summaryObjects, summaryLines):
++ threadMatches = t.summaryMatches[text]
++ for (attribute, description) in categories:
++- amount = int(threadMatches.group(attribute) if threadMatches else 0)
+++ amount = None
+++ if threadMatches:
+++ amount = int(threadMatches.group(attribute)
+++ else:
+++ amount = 0)
++ summaryObj[attribute] += amount
++- amount = int(threadMatches.group('total') if threadMatches else 0)
+++ amount = None
+++ if threadMatches:
+++ amount = int(threadMatches.group('total')
+++ else:
+++ amount = 0)
++ summaryObj['total'] += amount
++
++ print 'REFTEST INFO | Result summary:'
++diff -up comm-esr31/mozilla/media/libopus/gen-sources.py.python3 comm-esr31/mozilla/media/libopus/gen-sources.py
++--- comm-esr31/mozilla/media/libopus/gen-sources.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/media/libopus/gen-sources.py 2014-10-24 11:41:35.464880206 -0600
++@@ -27,14 +27,16 @@ def generate_sources_mozbuild(path):
++ ]
++
++ var_definition = re.compile('([A-Z_]*) = (.*)')
++- with open('sources.mozbuild', 'w') as output:
+++ output = open('sources.mozbuild', 'w')
+++ if 1:
++
++ output.write('# THIS FILE WAS AUTOMATICALLY GENERATED BY %s. DO NOT EDIT.\n' % sys.argv[0])
++ for makefile in makefiles:
++ values = []
++ definition_started = False
++
++- with open('%s/%s' % (path, makefile), 'r') as mk:
+++ mk = open('%s/%s' % (path, makefile), 'r')
+++ if 1:
++ for line in mk:
++ line = line.rstrip()
++ result = var_definition.match(line)
++@@ -60,8 +62,10 @@ def generate_sources_mozbuild(path):
++ add_value(values, result.group(2))
++ else:
++ add_value(values, line)
+++ mk.close()
++ write_values(output, values)
++
+++ output.close()
++ if __name__ == '__main__':
++ if len(sys.argv) != 2:
++ print "Usage: %s /path/to/opus" % (sys.argv[0])
++diff -up comm-esr31/mozilla/media/libvpx/update.py.python3 comm-esr31/mozilla/media/libvpx/update.py
++--- comm-esr31/mozilla/media/libvpx/update.py.python3 2014-07-17 18:05:38.000000000 -0600
+++++ comm-esr31/mozilla/media/libvpx/update.py 2014-10-24 11:41:35.464880206 -0600
++@@ -330,7 +330,8 @@ def get_sources(prefix):
++ disabled = {}
++
++ for mk in mk_files:
++- with open(os.path.join(prefix, mk)) as f:
+++ f = open(os.path.join(prefix, mk))
+++ if 1:
++ base = os.path.dirname(mk)
++ for l in f:
++ if '+=' in l:
++@@ -343,6 +344,7 @@ def get_sources(prefix):
++ source[key] = []
++ source[key].append(value)
++
+++ f.__exit__(0, 0, 0)
++ for key in source:
++ for f in source[key]:
++ if key.endswith('EXPORTS') and f.endswith('.h'):
++@@ -376,9 +378,11 @@ def update_sources_mozbuild(files, sourc
++ sources_mozbuild_new = "files = {\n %s\n}\n" % f.getvalue().strip()[1:-1]
++ if sources_mozbuild != sources_mozbuild_new:
++ print 'updating sources.mozbuild'
++- with open('sources.mozbuild', 'w') as f:
+++ f = open('sources.mozbuild', 'w')
+++ if 1:
++ f.write(sources_mozbuild_new)
++
+++ f.close()
++ def get_current_files():
++ current_files = []
++ for root, folders, files in os.walk('.'):
++@@ -396,8 +400,10 @@ def is_new(a, b):
++ or open(a).read() != open(b).read()
++
++ def get_sources_mozbuild():
++- with open('sources.mozbuild') as f:
+++ f = open('sources.mozbuild')
+++ if 1:
++ sources_mozbuild = f.read()
+++ f.__exit__(0, 0, 0)
++ exec(sources_mozbuild)
++ return sources_mozbuild, files
++
++@@ -455,9 +461,11 @@ def apply_patches():
++ os.system("patch -p3 < mingw.patch")
++
++ def update_readme(commit):
++- with open('README_MOZILLA') as f:
+++ f = open('README_MOZILLA').__enter__()
+++ if 1:
++ readme = f.read()
++
+++ f.close()
++ if 'The git commit ID used was' in readme:
++ new_readme = re.sub('The git commit ID used was [a-f0-9]+',
++ 'The git commit ID used was %s' % commit, readme)
++@@ -465,9 +473,11 @@ def update_readme(commit):
++ new_readme = "%s\n\nThe git commit ID used was %s\n" % (readme, commit)
++
++ if readme != new_readme:
++- with open('README_MOZILLA', 'w') as f:
+++ f = open('README_MOZILLA', 'w').__enter__()
+++ if 1:
++ f.write(new_readme)
++
+++ f.close()
++ def print_info(source, files, disabled, unknown, moz_build_files):
++ for key in moz_build_files:
++ if key not in files:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_monitor.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_monitor.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_monitor.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_monitor.py 2014-10-24 11:41:35.464880206 -0600
++@@ -121,8 +121,10 @@ def main(base_dir, adb_cmd='adb'):
++ pid_file_path = os.path.join(base_dir, 'LOGCAT_MONITOR_PID')
++
++ try:
++- with open(pid_file_path, 'w') as f:
+++ f = open(pid_file_path, 'w')
+++ if 1:
++ f.write(str(os.getpid()))
+++ f.close()
++ while True:
++ for device_id in GetAttachedDevices(adb_cmd):
++ if not device_id in devices:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_printer.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_printer.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_printer.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/adb_logcat_printer.py 2014-10-24 11:41:35.465880201 -0600
++@@ -110,8 +110,10 @@ def GetDeviceLogs(log_filenames, logger)
++ logger.debug('%s: %s', device, str(device_files))
++ device_file_lines = []
++ for cur_file in device_files:
++- with open(cur_file) as f:
+++ f = open(cur_file)
+++ if 1:
++ device_file_lines += [(cur_file, f.read().splitlines())]
+++ f.close()
++ combined_lines = CombineLogFiles(device_file_lines, logger)
++ # Prepend each line with a short unique ID so it's easy to see
++ # when the device changes. We don't use the start of the device
++@@ -126,9 +128,11 @@ def ShutdownLogcatMonitor(base_dir, logg
++ """Attempts to shutdown adb_logcat_monitor and blocks while waiting."""
++ try:
++ monitor_pid_path = os.path.join(base_dir, 'LOGCAT_MONITOR_PID')
++- with open(monitor_pid_path) as f:
+++ f = open(monitor_pid_path)
+++ if 1:
++ monitor_pid = int(f.readline())
++
+++ f.__exit__(0, 0, 0)
++ logger.info('Sending SIGTERM to %d', monitor_pid)
++ os.kill(monitor_pid, signal.SIGTERM)
++ i = 0
++@@ -184,9 +188,11 @@ def main(base_dir, output_file):
++ for log in GetDeviceLogs(FindLogFiles(base_dir), logger):
++ output_file.write(log)
++ output_file.write(separator)
++- with open(os.path.join(base_dir, 'eventlog')) as f:
+++ f = open(os.path.join(base_dir, 'eventlog')).__enter__()
+++ if 1:
++ output_file.write('\nLogcat Monitor Event Log\n')
++ output_file.write(f.read())
+++ f.close()
++ except:
++ logger.exception('Unexpected exception')
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/device_status_check.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/device_status_check.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/device_status_check.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/device_status_check.py 2014-10-24 11:41:35.465880201 -0600
++@@ -70,8 +70,10 @@ def CheckForMissingDevices(options, adb_
++ devices_path = os.path.join(out_dir, file_name)
++ devices = []
++ try:
++- with open(devices_path) as f:
+++ f = open(devices_path)
+++ if 1:
++ devices = f.read().splitlines()
+++ f.close()
++ except IOError:
++ # Ignore error, file might not exist
++ pass
++@@ -81,10 +83,12 @@ def CheckForMissingDevices(options, adb_
++ path = os.path.join(out_dir, file_name)
++ if not os.path.exists(out_dir):
++ os.makedirs(out_dir)
++- with open(path, 'w') as f:
+++ f = open(path, 'w')
+++ if 1:
++ # Write devices currently visible plus devices previously seen.
++ f.write('\n'.join(set(device_list)))
++
+++ f.close()
++ last_devices_path = os.path.join(out_dir, '.last_devices')
++ last_devices = ReadDeviceList('.last_devices')
++
++@@ -128,7 +132,7 @@ def CheckForMissingDevices(options, adb_
++ server = smtplib.SMTP('localhost')
++ server.sendmail(from_address, [to_address], msg_body)
++ server.quit()
++- except Exception as e:
+++ except Exception, e:
++ print 'Failed to send alert email. Error: %s' % e
++ else:
++ new_devs = set(adb_online_devs) - set(last_devices)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/emulator.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/emulator.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/emulator.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/emulator.py 2014-10-24 11:41:35.465880201 -0600
++@@ -275,7 +275,7 @@ class Emulator(object):
++ number_of_waits -= 1
++ if not number_of_waits:
++ break
++- except errors.WaitForResponseTimedOutError as e:
+++ except errors.WaitForResponseTimedOutError, e:
++ seconds_waited += self._WAITFORDEVICE_TIMEOUT
++ adb_cmd = "adb -s %s %s" % (self.device, 'kill-server')
++ run_command.RunCommand(adb_cmd)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/lighttpd_server.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/lighttpd_server.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/lighttpd_server.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/lighttpd_server.py 2014-10-24 11:41:35.465880201 -0600
++@@ -77,15 +77,19 @@ class LighttpdServer(object):
++ while True:
++ if self.base_config_path:
++ # Read the config
++- with codecs.open(self.base_config_path, 'r', 'utf-8') as f:
+++ f = codecs.open(self.base_config_path, 'r', 'utf-8').__enter__()
+++ if 1:
++ config_contents = f.read()
+++ f.__exit__(0, 0, 0)
++ else:
++ config_contents = self._GetDefaultBaseConfig()
++ if self.extra_config_contents:
++ config_contents += self.extra_config_contents
++ # Write out the config, filling in placeholders from the members of |self|
++- with codecs.open(self.config_path, 'w', 'utf-8') as f:
+++ f = codecs.open(self.config_path, 'w', 'utf-8').__enter__()
+++ if 1:
++ f.write(config_contents % self.__dict__)
+++ f.__exit__(0, 0, 0)
++ if (not os.path.exists(self.lighttpd_path) or
++ not os.access(self.lighttpd_path, os.X_OK)):
++ raise EnvironmentError(
++@@ -133,7 +137,7 @@ class LighttpdServer(object):
++ client_error = ('Bad response: %s %s version %s\n ' %
++ (r.status, r.reason, r.version) +
++ '\n '.join([': '.join(h) for h in r.getheaders()]))
++- except (httplib.HTTPException, socket.error) as client_error:
+++ except (httplib.HTTPException, socket.error), client_error:
++ pass # Probably too quick connecting: try again
++ # Check for server startup error messages
++ ix = self.process.expect([pexpect.TIMEOUT, pexpect.EOF, '.+'],
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/android_commands.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/android_commands.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/android_commands.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/android_commands.py 2014-10-24 11:41:35.466880197 -0600
++@@ -251,7 +251,7 @@ class AndroidCommands(object):
++ try:
++ self._adb.WaitForDevicePm()
++ return # Success
++- except errors.WaitForResponseTimedOutError as e:
+++ except errors.WaitForResponseTimedOutError, e:
++ last_err = e
++ logging.warning('Restarting and retrying after timeout: %s', e)
++ retries -= 1
++@@ -624,11 +624,13 @@ class AndroidCommands(object):
++
++ def SetFileContents(self, filename, contents):
++ """Writes |contents| to the file specified by |filename|."""
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ f.write(contents)
++ f.flush()
++ self._adb.Push(f.name, filename)
++
+++ f.__exit__(0, 0, 0)
++ def RemovePushedFiles(self):
++ """Removes all files pushed with PushIfNeeded() from the device."""
++ for p in self._pushed_files:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/device_stats_monitor.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/device_stats_monitor.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/device_stats_monitor.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/device_stats_monitor.py 2014-10-24 11:41:35.466880197 -0600
++@@ -92,8 +92,10 @@ class DeviceStatsMonitor(object):
++ 'irq': 'jiffies',
++ 'softirq': 'jiffies',
++ }
++- with open(output_path, 'w') as f:
+++ f = open(output_path, 'w')
+++ if 1:
++ f.write('display(%d, %s, %s);' % (self._hz, json.dumps(results), units))
+++ f.close()
++ return 'file://%s?results=file://%s' % (
++ DeviceStatsMonitor.RESULT_VIEWER_PATH, urllib.quote(output_path))
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/forwarder.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/forwarder.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/forwarder.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/forwarder.py 2014-10-24 11:41:35.466880197 -0600
++@@ -117,8 +117,7 @@ class Forwarder(object):
++ forward_string)
++
++ # Read the output of the command to determine which device ports where
++- # forwarded to which host ports (necessary if
++- host_success_re = re.compile('Forwarding device port (\d+) to host (\d+):')
+++ # forwarded to which host ports (necessary if host_success_re = re.compile('Forwarding device port (\d+) to host (\d+):')
++ host_failure_re = re.compile('Couldn\'t start forwarder server for port '
++ 'spec: (\d+):(\d+)')
++ for pair in port_pairs:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/json_perf_parser.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/json_perf_parser.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/json_perf_parser.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/json_perf_parser.py 2014-10-24 11:41:35.466880197 -0600
++@@ -153,8 +153,10 @@ def GetAverageRunInfoFromFile(json_file,
++ Returns:
++ See GetAverageRunInfo Returns section.
++ """
++- with open(json_file, 'r') as f:
+++ f = open(json_file, 'r')
+++ if 1:
++ data = f.read()
++ perf = json.loads(data)
++
+++ f.close()
++ return GetAverageRunInfo(perf, name)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/perf_tests_helper.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/perf_tests_helper.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/perf_tests_helper.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/perf_tests_helper.py 2014-10-24 11:41:35.466880197 -0600
++@@ -67,7 +67,7 @@ def PrintPerfResult(measurement, trace,
++ trace_name,
++ # Do not show equal sign if the trace is empty. Usually it happens when
++ # measurement is enough clear to describe the result.
++- '= ' if trace_name else '',
+++ ('', '= ')[trace_name],
++ value,
++ units)
++ if avg:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/ports.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/ports.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/ports.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/ports.py 2014-10-24 11:41:35.467880193 -0600
++@@ -28,12 +28,14 @@ def ResetTestServerPortAllocation():
++ Returns True if reset successes. Otherwise returns False.
++ """
++ try:
++- with open(constants.TEST_SERVER_PORT_FILE, 'w') as fp:
+++ fp = open(constants.TEST_SERVER_PORT_FILE, 'w')
+++ if 1:
++ fp.write('%d' % constants.TEST_SERVER_PORT_FIRST)
+++ fp.__exit__(0, 0, 0)
++ if os.path.exists(constants.TEST_SERVER_PORT_LOCKFILE):
++ os.unlink(constants.TEST_SERVER_PORT_LOCKFILE)
++ return True
++- except Exception as e:
+++ except Exception, e:
++ logging.error(e)
++ return False
++
++@@ -52,7 +54,8 @@ def AllocateTestServerPort():
++ fcntl.flock(fp_lock, fcntl.LOCK_EX)
++ # Get current valid port and calculate next valid port.
++ assert os.path.exists(constants.TEST_SERVER_PORT_FILE)
++- with open(constants.TEST_SERVER_PORT_FILE, 'r+') as fp:
+++ fp = open(constants.TEST_SERVER_PORT_FILE, 'r+').__enter__()
+++ if 1:
++ port = int(fp.read())
++ ports_tried.append(port)
++ while IsHostPortUsed(port):
++@@ -62,9 +65,10 @@ def AllocateTestServerPort():
++ port < constants.TEST_SERVER_PORT_FIRST):
++ port = 0
++ else:
++- fp.seek(0, os.SEEK_SET)
+++ fp.seek(0, 0)
++ fp.write('%d' % (port + 1))
++- except Exception as e:
+++ fp.close()
+++ except Exception, e:
++ logging.info(e)
++ finally:
++ if fp_lock:
++@@ -114,7 +118,11 @@ def IsDevicePortUsed(adb, device_port, s
++ for single_connect in netstat_results:
++ # Column 3 is the local address which we want to check with.
++ connect_results = single_connect.split()
++- is_state_match = connect_results[5] == state if state else True
+++ is_state_match = None
+++ if state:
+++ is_state_match = connect_results[5] == state
+++ else:
+++ is_state_match = True
++ if connect_results[3] == base_url and is_state_match:
++ return True
++ return False
++@@ -158,7 +166,7 @@ def IsHttpServerConnectable(host, port,
++ client_error = ('Bad response: %s %s version %s\n ' %
++ (r.status, r.reason, r.version) +
++ '\n '.join([': '.join(h) for h in r.getheaders()]))
++- except (httplib.HTTPException, socket.error) as e:
+++ except (httplib.HTTPException, socket.error), e:
++ # Probably too quick connecting: try again.
++ exception_error_msgs = traceback.format_exception_only(type(e), e)
++ if exception_error_msgs:
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/run_java_tests.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/run_java_tests.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/run_java_tests.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/run_java_tests.py 2014-10-24 11:41:35.467880193 -0600
++@@ -382,8 +382,10 @@ class TestRunner(BaseTestRunner):
++
++ if self.save_perf_json:
++ json_local_file = '/tmp/chromium-android-perf-json-' + raw_test_name
++- with open(json_local_file, 'w') as f:
+++ f = open(json_local_file, 'w')
+++ if 1:
++ f.write(json_string)
+++ f.close()
++ logging.info('Saving Perf UI JSON from test ' +
++ test + ' to ' + json_local_file)
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_info_collection.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_info_collection.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_info_collection.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_info_collection.py 2014-10-24 11:41:35.467880193 -0600
++@@ -78,20 +78,17 @@ class TestInfoCollection(object):
++
++ # Filter out tests which match neither the requested annotation, nor the
++ # requested name filter, if any.
++- available_tests = [t for t in available_tests if
++- self._AnnotationIncludesTest(t, annotation)]
+++ available_tests = [t for t in available_tests if self._AnnotationIncludesTest(t, annotation)]
++ if annotation and len(annotation) == 1 and annotation[0] == 'SmallTest':
++ tests_without_annotation = [
++- t for t in self.all_tests if
++- not tests_annotations.AnnotatedFunctions.GetTestAnnotations(
+++ t for t in self.all_tests if not tests_annotations.AnnotatedFunctions.GetTestAnnotations(
++ t.qualified_name)]
++ test_names = [t.qualified_name for t in tests_without_annotation]
++ logging.warning('The following tests do not contain any annotation. '
++ 'Assuming "SmallTest":\n%s',
++ '\n'.join(test_names))
++ available_tests += tests_without_annotation
++- available_tests = [t for t in available_tests if
++- self._NameFilterIncludesTest(t, name_filter)]
+++ available_tests = [t for t in available_tests if self._NameFilterIncludesTest(t, name_filter)]
++
++ return available_tests
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_result.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_result.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_result.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/pylib/test_result.py 2014-10-24 11:41:35.467880193 -0600
++@@ -145,10 +145,12 @@ class TestResults(object):
++ os.mkdir(log_file_path)
++ full_file_name = os.path.join(log_file_path, test_group)
++ if not os.path.exists(full_file_name):
++- with open(full_file_name, 'w') as log_file:
+++ log_file = open(full_file_name, 'w')
+++ if 1:
++ print >> log_file, '\n%s results for %s build %s:' % (
++ test_group, os.environ.get('BUILDBOT_BUILDERNAME'),
++ os.environ.get('BUILDBOT_BUILDNUMBER'))
+++ log_file.close()
++ log_contents = [' %s result : %d tests ran' % (test_suite,
++ len(self.ok) +
++ len(self.failed) +
++@@ -159,16 +161,20 @@ class TestResults(object):
++ for (result, count) in content_pairs:
++ if count:
++ log_contents.append(', %d tests %s' % (count, result))
++- with open(full_file_name, 'a') as log_file:
+++ log_file = open(full_file_name, 'a')
+++ if 1:
++ print >> log_file, ''.join(log_contents)
+++ log_file.close()
++ content = {'test_group': test_group,
++ 'ok': [t.name for t in self.ok],
++ 'failed': [t.name for t in self.failed],
++ 'crashed': [t.name for t in self.failed],
++ 'unknown': [t.name for t in self.unknown],}
++- with open(os.path.join(log_file_path, 'results.json'), 'a') as json_file:
+++ json_file = open(os.path.join(log_file_path, 'results.json'), 'a')
+++ if 1:
++ print >> json_file, json.dumps(content)
++
+++ json_file.close()
++ # Summarize in the test output.
++ summary_string = 'Summary:\n'
++ summary_string += 'RAN=%d\n' % (len(self.ok) + len(self.failed) +
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/android/run_tests.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/android/run_tests.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/android/run_tests.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/android/run_tests.py 2014-10-24 11:41:35.468880189 -0600
++@@ -147,7 +147,7 @@ class Xvfb(object):
++ self._pid = 0
++
++ def _IsLinux(self):
++- """Return True if on Linux; else False."""
+++ """Return Trueon Linux; = (False.""", )[]
++ return sys.platform.startswith('linux')
++
++ def Start(self):
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/escape_unicode.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/escape_unicode.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/escape_unicode.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/escape_unicode.py 2014-10-24 11:41:35.468880189 -0600
++@@ -42,7 +42,8 @@ def main(argv):
++
++ def WriteEscapedFile(in_filename, out_filename):
++ input_data = codecs.open(in_filename, 'r', 'utf8').read()
++- with codecs.open(out_filename, 'w', 'ascii') as out_file:
+++ out_file = codecs.open(out_filename, 'w', 'ascii').__enter__()
+++ if 1:
++ for i, char in enumerate(input_data):
++ if ord(char) > 127:
++ out_file.write(repr(char.encode('utf8'))[1:-1])
++@@ -52,5 +53,6 @@ def WriteEscapedFile(in_filename, out_fi
++ out_file.write(char.encode('ascii'))
++
++
+++ out_file.__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ sys.exit(main(sys.argv))
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/mac/change_mach_o_flags.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/mac/change_mach_o_flags.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/mac/change_mach_o_flags.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/mac/change_mach_o_flags.py 2014-10-24 11:41:35.468880189 -0600
++@@ -103,7 +103,7 @@ def CheckedSeek(file, offset):
++ """Seeks the file-like object at |file| to offset |offset| and raises a
++ MachOError if anything funny happens."""
++
++- file.seek(offset, os.SEEK_SET)
+++ file.seek(offset, 0)
++ new_offset = file.tell()
++ if new_offset != offset:
++ raise MachOError, \
++diff -up comm-esr31/mozilla/media/webrtc/trunk/build/mac/tweak_info_plist.py.python3 comm-esr31/mozilla/media/webrtc/trunk/build/mac/tweak_info_plist.py
++--- comm-esr31/mozilla/media/webrtc/trunk/build/mac/tweak_info_plist.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/build/mac/tweak_info_plist.py 2014-10-24 11:41:35.468880189 -0600
++@@ -125,8 +125,7 @@ def _DoSCMKeys(plist, add_keys):
++
++ def _DoPDFKeys(plist, add_keys):
++ """Adds PDF support to the document types list. If add_keys is True, it will
++- add the type information dictionary. If it is False, it will remove it if
++- present."""
+++ add the type information dictionary. If it is False, it will remove it if present."""
++
++ PDF_FILE_EXTENSION = 'pdf'
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/testing/gtest/test/gtest_xml_output_unittest.py.python3 comm-esr31/mozilla/media/webrtc/trunk/testing/gtest/test/gtest_xml_output_unittest.py
++--- comm-esr31/mozilla/media/webrtc/trunk/testing/gtest/test/gtest_xml_output_unittest.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/testing/gtest/test/gtest_xml_output_unittest.py 2014-10-24 11:41:35.468880189 -0600
++@@ -166,8 +166,7 @@ class GTestXMLOutputUnitTest(gtest_xml_t
++ def testTimestampValue(self):
++ """Checks whether the timestamp attribute in the XML output is valid.
++
++- Runs a test program that generates an empty XML output, and checks if
++- the timestamp attribute in the testsuites tag is valid.
+++ Runs a test program that generates an empty XML output, and checks if the timestamp attribute in the testsuites tag is valid.
++ """
++ actual = self._GetXmlOutput('gtest_no_test_unittest', 0)
++ date_time_str = actual.documentElement.getAttributeNode('timestamp').value
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py 2014-10-24 11:41:35.469880185 -0600
++@@ -2,7 +2,7 @@
++ # Use of this source code is governed by a BSD-style license that can be
++ # found in the LICENSE file.
++
++-from __future__ import with_statement
+++
++
++ import errno
++ import filecmp
++@@ -392,15 +392,19 @@ def CopyTool(flavor, out_path):
++ # Slurp input file.
++ source_path = os.path.join(
++ os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix)
++- with open(source_path) as source_file:
+++ source_file = open(source_path)
+++ if 1:
++ source = source_file.readlines()
++
+++ source_file.close()
++ # Add header and write it out.
++ tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix)
++- with open(tool_path, 'w') as tool_file:
+++ tool_file = open(tool_path, 'w')
+++ if 1:
++ tool_file.write(
++ ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:]))
++
+++ tool_file.close()
++ # Make file executable.
++ os.chmod(tool_path, 0755)
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/msvs.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/msvs.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/msvs.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/msvs.py 2014-10-24 11:41:35.469880185 -0600
++@@ -305,7 +305,11 @@ def _BuildCommandLineForRuleRaw(spec, cm
++ # for arguments like "--arg=path" or "/opt:path".
++ # If the argument starts with a slash or dash, it's probably a command line
++ # switch
++- arguments = [i if (i[:1] in "/-") else _FixPath(i) for i in cmd[1:]]
+++ arguments = None
+++ if (i[:1] in "/-"):
+++ arguments = [i
+++ else:
+++ arguments = _FixPath(i) for i in cmd[1:]]
++ arguments = [i.replace('$(InputDir)','%INPUTDIR%') for i in arguments]
++ arguments = [MSVSSettings.FixVCMacroSlashes(i) for i in arguments]
++ if quote_cmd:
++@@ -695,8 +699,7 @@ def _EscapeVCProjCommandLineArgListItem(
++ # .vcproj file will be misinterpreted as part of this item. There is nothing
++ # we can do about this. Adding an extra quote would correct the problem in
++ # the VCProj but cause the same problem on the final command-line. Moving
++- # the item to the end of the list does works, but that's only possible if
++- # there's only one such item. Let's just warn the user.
+++ # the item to the end of the list does works, but that's only possible if # there's only one such item. Let's just warn the user.
++ print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' +
++ 'quotes in ' + s)
++ return s
++@@ -1484,7 +1487,7 @@ def _AddActions(actions_to_add, spec, re
++ # and does not need to be set up again.
++ have_setup_env = set()
++ for a in actions:
++- # Attach actions to the gyp file if nothing else is there.
+++ # Attach actions to the gyp filenothing = (is there., )[]
++ inputs = a.get('inputs') or [relative_path_of_gyp_file]
++ attached_to = inputs[0]
++ need_setup_env = attached_to not in have_setup_env
++@@ -2632,8 +2635,7 @@ def _GetMSBuildAttributes(spec, config,
++
++
++ def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
++- # TODO(jeanluc) We could optimize out the following and do it only if
++- # there are actions.
+++ # TODO(jeanluc) We could optimize out the following and do it only if # there are actions.
++ # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'.
++ new_paths = []
++ cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0]
++@@ -2802,8 +2804,7 @@ def _FinalizeMSBuildSettings(spec, confi
++ precompiled_header = configuration.get('msvs_precompiled_header')
++
++ # Add the information to the appropriate tool
++- # TODO(jeanluc) We could optimize and generate these settings only if
++- # the corresponding files are found, e.g. don't generate ResourceCompile
+++ # TODO(jeanluc) We could optimize and generate these settings only if # the corresponding files are found, e.g. don't generate ResourceCompile
++ # if you don't have any resources.
++ _ToolAppend(msbuild_settings, 'ClCompile',
++ 'AdditionalIncludeDirectories', include_dirs)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/ninja.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/ninja.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/ninja.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/ninja.py 2014-10-24 11:41:35.470880180 -0600
++@@ -233,7 +233,7 @@ class NinjaWriter:
++ self.ninja = ninja_syntax.Writer(output_file)
++ self.flavor = flavor
++ self.abs_build_dir = abs_build_dir
++- self.obj_ext = '.obj' if flavor == 'win' else '.o'
+++ self.obj_ext = ('.o', '.obj')[flavor == 'win']
++ if flavor == 'win':
++ # See docstring of msvs_emulation.GenerateEnvironmentFiles().
++ self.win_env = {}
++@@ -551,8 +551,11 @@ class NinjaWriter:
++ description = self.GenerateDescription('ACTION',
++ action.get('message', None),
++ name)
++- is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action)
++- if self.flavor == 'win' else False)
+++ is_cygwin = None
+++ if self.flavor == 'win':
+++ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action))
+++ else:
+++ is_cygwin = (False)
++ args = action['action']
++ rule_name, _ = self.WriteNewNinjaRule(name, args, description,
++ is_cygwin, env=env)
++@@ -589,8 +592,11 @@ class NinjaWriter:
++ 'RULE',
++ rule.get('message', None),
++ ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
++- is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule)
++- if self.flavor == 'win' else False)
+++ is_cygwin = None
+++ if self.flavor == 'win':
+++ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule))
+++ else:
+++ is_cygwin = (False)
++ rule_name, args = self.WriteNewNinjaRule(
++ name, args, description, is_cygwin, env=env)
++
++@@ -1204,7 +1210,7 @@ class NinjaWriter:
++ if self.flavor == 'win':
++ rspfile = rule_name + '.$unique_name.rsp'
++ # The cygwin case handles this inside the bash sub-shell.
++- run_in = '' if is_cygwin else ' ' + self.build_to_base
+++ run_in = (' ' + self.build_to_base, '' )[is_cygwin]
++ if is_cygwin:
++ rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(
++ args, self.build_to_base)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/xcode.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/xcode.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/xcode.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/xcode.py 2014-10-24 11:41:35.470880180 -0600
++@@ -1090,8 +1090,7 @@ exit 1
++ else:
++ pbxp.AddOrGetFileInRootGroup(source)
++
++- # Add "mac_bundle_resources" and "mac_framework_private_headers" if
++- # it's a bundle of any type.
+++ # Add "mac_bundle_resources" and "mac_framework_private_headers" if # it's a bundle of any type.
++ if is_bundle:
++ for resource in tgt_mac_bundle_resources:
++ (resource_root, resource_extension) = posixpath.splitext(resource)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py 2014-10-24 11:41:35.471880176 -0600
++@@ -12,7 +12,7 @@ from compiler.ast import Stmt
++ import compiler
++ import copy
++ import gyp.common
++-import multiprocessing
+++#import multiprocessing
++ import optparse
++ import os.path
++ import re
++@@ -997,8 +997,7 @@ def ProcessConditionsInDict(the_dict, ph
++ # Each item in a conditions list consists of cond_expr, a string expression
++ # evaluated as the condition, and true_dict, a dict that will be merged into
++ # the_dict if cond_expr evaluates to true. Optionally, a third item,
++- # false_dict, may be present. false_dict is merged into the_dict if
++- # cond_expr evaluates to false.
+++ # false_dict, may be present. false_dict is merged into the_dict if # cond_expr evaluates to false.
++ #
++ # Any dict merged into the_dict will be recursively processed for nested
++ # conditionals and other expansions, also according to phase, immediately
++@@ -1202,8 +1201,7 @@ def ProcessVariablesAndConditionsInDict(
++ # Recurse into child dicts, or process child lists which may result in
++ # further recursion into descendant dicts.
++ for key, value in the_dict.iteritems():
++- # Skip "variables" and string values, which were already processed if
++- # present.
+++ # Skip "variables" and string values, which were already processed if # present.
++ if key == 'variables' or isinstance(value, str):
++ continue
++ if isinstance(value, dict):
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/msvs_emulation.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/msvs_emulation.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/msvs_emulation.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/msvs_emulation.py 2014-10-24 11:41:35.471880176 -0600
++@@ -170,7 +170,7 @@ class MsvsSettings(object):
++ replacements = {
++ '$(VSInstallDir)': self.vs_version.Path(),
++ '$(VCInstallDir)': os.path.join(self.vs_version.Path(), 'VC') + '\\',
++- '$(OutDir)\\': base_to_build + '\\' if base_to_build else '',
+++ '$(OutDir)\\': base_to_build + ('', '\\')[base_to_build],
++ '$(IntDir)': '$!INTERMEDIATE_DIR',
++ '$(InputPath)': '${source}',
++ '$(InputName)': '${root}',
++@@ -182,8 +182,7 @@ class MsvsSettings(object):
++ # set. This happens when the SDK is sync'd via src-internal, rather than
++ # by typical end-user installation of the SDK. If it's not set, we don't
++ # want to leave the unexpanded variable in the path, so simply strip it.
++- replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
++- replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
+++ replacements['$(DXSDK_DIR)'] = ('', self.wdk_dir)[self.wdk_dir]
++ return replacements
++
++ def ConvertVSMacros(self, s, base_to_build=None, config=None):
++@@ -192,8 +191,10 @@ class MsvsSettings(object):
++ return ExpandMacros(s, env)
++
++ def AdjustLibraries(self, libraries):
++- """Strip -l from library if it's specified with that."""
++- return [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
+++ """Strip -l from library if it's specified with that.""" if lib.startswith('-l'):
+++ return [lib[2:]
+++ else:
+++ return lib for lib in libraries]
++
++ def _GetAndMunge(self, field, path, default, prefix, append, map):
++ """Retrieve a value from |field| at |path| or return |default|. If
++@@ -269,7 +270,7 @@ class MsvsSettings(object):
++ if it's not overridden."""
++ config = self._RealConfig(config)
++ type = self.spec['type']
++- root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool'
+++ root = ('VCLinkerTool', 'VCLibrarianTool')[type == 'static_library']
++ # TODO(scottmg): Handle OutputDirectory without OutputFile.
++ output_file = self._Setting((root, 'OutputFile'), config)
++ if output_file:
++@@ -597,7 +598,7 @@ class PrecompiledHeader(object):
++ if not source or not header:
++ return []
++ ext = os.path.splitext(source)[1]
++- lang = 'c' if ext == '.c' else 'cc'
+++ lang = ('cc', 'c')[ext == '.c']
++ return [(self._PchOutput(), '/Yc' + header, lang, source)]
++
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/MSVSUserFile.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/MSVSUserFile.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/MSVSUserFile.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/MSVSUserFile.py 2014-10-24 11:41:35.471880176 -0600
++@@ -81,8 +81,7 @@ class Writer(object):
++
++ Args:
++ command: command line to run. First element in the list is the
++- executable. All elements of the command will be quoted if
++- necessary.
+++ executable. All elements of the command will be quoted if necessary.
++ working_directory: other files which may trigger the rule. (optional)
++ """
++ command = _QuoteWin32CommandLineArgs(command)
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/SCons.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/SCons.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/SCons.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/SCons.py 2014-10-24 11:41:35.472880172 -0600
++@@ -34,7 +34,7 @@ class TargetBase(object):
++ """
++ Returns the full name of the product being built:
++
++- * Uses 'product_name' if it's set, else prefix + 'target_name'.
+++ * Uses 'product_name'it's set, = (prefix + 'target_name'., )[]
++ * Prepends 'product_dir' if set.
++ * Appends SCons suffix variables for the target type (or
++ product_extension).
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/win_tool.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/win_tool.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/win_tool.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/win_tool.py 2014-10-24 11:41:35.472880172 -0600
++@@ -96,7 +96,8 @@ class WinTool(object):
++ ' Creating library ui.dll.lib and object ui.dll.exp'
++ This happens when there are exports from the dll or exe.
++ """
++- with LinkLock():
+++ LinkLock().__enter__()
+++ if 1:
++ env = self._GetEnv(arch)
++ popen = subprocess.Popen(args, shell=True, env=env,
++ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
++@@ -106,6 +107,7 @@ class WinTool(object):
++ print line
++ return popen.returncode
++
+++ LinkLock().__exit__(0, 0, 0)
++ def ExecManifestWrapper(self, arch, *args):
++ """Run manifest tool with environment set. Strip out undesirable warning
++ (some XML blocks are recognized by the OS loader, but not the manifest
++@@ -184,7 +186,11 @@ class WinTool(object):
++ for |arch|. If |dir| is supplied, use that as the working directory."""
++ env = self._GetEnv(arch)
++ args = open(rspfile).read()
++- dir = dir[0] if dir else None
+++ dir = None
+++ if dir:
+++ dir = dir[0]
+++ else:
+++ dir = None
++ popen = subprocess.Popen(args, shell=True, env=env, cwd=dir)
++ popen.wait()
++ return popen.returncode
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcode_emulation.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcode_emulation.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcode_emulation.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcode_emulation.py 2014-10-24 11:41:35.472880172 -0600
++@@ -415,7 +415,7 @@ class XcodeSettings(object):
++ return None
++ install_base = self.GetPerTargetSetting(
++ 'DYLIB_INSTALL_NAME_BASE',
++- default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib')
+++ default=('/usr/local/lib', '/Library/Frameworks')[self._IsBundle()])
++ return install_base
++
++ def _StandardizePath(self, path):
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcodeproj_file.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcodeproj_file.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcodeproj_file.py.python3 2014-07-17 18:05:40.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/pylib/gyp/xcodeproj_file.py 2014-10-24 11:41:35.473880168 -0600
++@@ -216,8 +216,7 @@ class XCObject(object):
++ is_strong: If property_type is an XCObject subclass, is_strong
++ is True to assert that this class "owns," or serves
++ as parent, to the property value (or, if is_list is
++- True, values). is_strong must be False if
++- property_type is not an XCObject subclass.
+++ True, values). is_strong must be False if property_type is not an XCObject subclass.
++ is_required: True if the property is required for the class.
++ Note that is_required being True does not preclude
++ an empty string ("", in the case of property_type
++@@ -954,8 +953,7 @@ class XCHierarchicalElement(XCObject):
++
++ XCHierarchicalElements are special. Generally, their hashes shouldn't
++ change if the paths don't change. The normal XCObject implementation of
++- Hashables adds a hashable for each object, which means that if
++- the hierarchical structure changes (possibly due to changes caused when
+++ Hashables adds a hashable for each object, which means that if the hierarchical structure changes (possibly due to changes caused when
++ TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
++ the hashes will change. For example, if a project file initially contains
++ a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
++@@ -2132,8 +2130,7 @@ class XCTarget(XCRemoteObject):
++
++ # Set up additional defaults not expressed in the schema. If a "name"
++ # property was supplied, set "productName" if it is not present. Also set
++- # the "PRODUCT_NAME" build setting in each configuration, but only if
++- # the setting is not present in any build configuration.
+++ # the "PRODUCT_NAME" build setting in each configuration, but only if # the setting is not present in any build configuration.
++ if 'name' in self._properties:
++ if not 'productName' in self._properties:
++ self.SetProperty('productName', self._properties['name'])
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/library/gyptest-shared-obj-install-path.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/library/gyptest-shared-obj-install-path.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/library/gyptest-shared-obj-install-path.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/library/gyptest-shared-obj-install-path.py 2014-10-24 11:41:35.473880168 -0600
++@@ -10,7 +10,7 @@ their install location rather than by th
++ """
++
++ # Python 2.5 needs this for the with statement.
++-from __future__ import with_statement
+++
++
++ import os
++ import TestGyp
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCmd.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCmd.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCmd.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCmd.py 2014-10-24 11:41:35.473880168 -0600
++@@ -1127,8 +1127,10 @@ class TestCmd(object):
++ file = self.canonicalize(file)
++ if mode[0] != 'r':
++ raise ValueError, "mode must begin with 'r'"
++- with open(file, mode) as f:
+++ f = open(file, mode)
+++ if 1:
++ result = f.read()
+++ f.__exit__(0, 0, 0)
++ return result
++
++ def rmdir(self, dir):
++@@ -1587,9 +1589,11 @@ class TestCmd(object):
++ file = self.canonicalize(file)
++ if mode[0] != 'w':
++ raise ValueError, "mode must begin with 'w'"
++- with open(file, mode) as f:
+++ f = open(file, mode).__enter__()
+++ if 1:
++ f.write(content)
++
+++ f.close()
++ # Local Variables:
++ # tab-width:4
++ # indent-tabs-mode:nil
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCommon.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCommon.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCommon.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/lib/TestCommon.py 2014-10-24 11:41:35.474880163 -0600
++@@ -499,7 +499,8 @@ class TestCommon(TestCmd):
++ """Runs the program under test, checking that the test succeeded.
++
++ The arguments are the same as the base TestCmd.run() method,
++- with the addition of:
+++ the addition of.__enter__()
+++ if 1:
++
++ options Extra options that get appended to the beginning
++ of the arguments.
++@@ -516,6 +517,7 @@ class TestCommon(TestCmd):
++ command. A value of None means don't
++ test exit status.
++
+++ the addition of.__exit__(0, 0, 0)
++ By default, this expects a successful exit (status = 0), does
++ not test standard output (stdout = None), and expects that error
++ output is empty (stderr = "").
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/make/gyptest-noload.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/make/gyptest-noload.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/make/gyptest-noload.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/make/gyptest-noload.py 2014-10-24 11:41:35.474880163 -0600
++@@ -10,7 +10,7 @@ optional.
++ """
++
++ # Python 2.5 needs this for the with statement.
++-from __future__ import with_statement
+++
++
++ import os
++ import TestGyp
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py 2014-10-24 11:41:35.474880163 -0600
++@@ -27,7 +27,7 @@ test.run_gyp('action_dependencies.gyp',
++ chdir = 'relocate/src'
++ test.relocate('src', chdir)
++
++-objext = '.obj' if sys.platform == 'win32' else '.o'
+++objext = ('.o', '.obj')[sys.platform == 'win32']
++
++ test.build('action_dependencies.gyp',
++ os.path.join('obj', 'b.b' + objext),
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py.python3 2014-07-17 18:05:41.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py 2014-10-24 11:41:35.474880163 -0600
++@@ -19,7 +19,7 @@ import TestGyp
++
++ test = TestGyp.TestGyp(formats=['ninja'])
++ test.run_gyp('chained-dependency.gyp')
++-objext = '.obj' if sys.platform == 'win32' else '.o'
+++objext = ('.o', '.obj')[sys.platform == 'win32']
++ test.build('chained-dependency.gyp',
++ os.path.join('obj', 'chained.chained' + objext))
++ # The test passes if the .o file builds successfully.
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-cl-function-level-linking.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-cl-function-level-linking.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-cl-function-level-linking.py.python3 2014-07-17 18:05:42.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-cl-function-level-linking.py 2014-10-24 11:41:35.474880163 -0600
++@@ -29,7 +29,7 @@ if sys.platform == 'win32':
++ test.fail_test()
++
++ def Object(proj, obj):
++- sep = '.' if test.format == 'ninja' else '\\'
+++ sep = ('\\', '.')[test.format == 'ninja']
++ return 'obj\\%s%s%s' % (proj, sep, obj)
++
++ look_for = '''COMDAT; sym= "int __cdecl comdat_function'''
++diff -up comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-link-debug-info.py.python3 comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-link-debug-info.py
++--- comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-link-debug-info.py.python3 2014-07-17 18:05:42.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/tools/gyp/test/win/gyptest-link-debug-info.py 2014-10-24 11:41:35.474880163 -0600
++@@ -19,7 +19,7 @@ if sys.platform == 'win32':
++ test.run_gyp('debug-info.gyp', chdir=CHDIR)
++ test.build('debug-info.gyp', test.ALL, chdir=CHDIR)
++
++- suffix = '.exe.pdb' if test.format == 'ninja' else '.pdb'
+++ suffix = ('.pdb', '.exe.pdb')[test.format == 'ninja']
++ test.built_file_must_not_exist('test_debug_off%s' % suffix, chdir=CHDIR)
++ test.built_file_must_exist('test_debug_on%s' % suffix, chdir=CHDIR)
++
++diff -up comm-esr31/mozilla/media/webrtc/trunk/webrtc/test/buildbot_tests.py.python3 comm-esr31/mozilla/media/webrtc/trunk/webrtc/test/buildbot_tests.py
++--- comm-esr31/mozilla/media/webrtc/trunk/webrtc/test/buildbot_tests.py.python3 2014-07-17 18:05:43.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/webrtc/test/buildbot_tests.py 2014-10-24 11:41:35.475880159 -0600
++@@ -128,7 +128,7 @@ def main():
++ print 'Running: %s' % ' '.join(cmd_line)
++ try:
++ subprocess.check_call(cmd_line, env=env)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ print >> sys.stderr, ('An error occurred during test execution: return '
++ 'code: %d' % e.returncode)
++ return -1
++diff -up comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_decoder.py.python3 comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_decoder.py
++--- comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_decoder.py.python3 2014-07-17 18:05:43.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_decoder.py 2014-10-24 11:41:35.475880159 -0600
++@@ -39,7 +39,7 @@ def convert_yuv_to_png_files(yuv_file_na
++ """
++ size_string = str(yuv_frame_width) + 'x' + str(yuv_frame_height)
++ output_files_pattern = os.path.join(output_directory, 'frame_%04d.png')
++- ffmpeg_executable = 'ffmpeg.exe' if sys.platform == 'win32' else 'ffmpeg'
+++ ffmpeg_executable = ('ffmpeg', 'ffmpeg.exe')[sys.platform == 'win32']
++ if ffmpeg_dir:
++ ffmpeg_executable = os.path.join(ffmpeg_dir, ffmpeg_executable)
++ command = [ffmpeg_executable, '-s', '%s' % size_string, '-i', '%s'
++@@ -78,7 +78,7 @@ def decode_frames(input_directory, zxing
++ Return:
++ (bool): True if the decoding went without errors.
++ """
++- zxing_executable = 'zxing.exe' if sys.platform == 'win32' else 'zxing'
+++ zxing_executable = ('zxing', 'zxing.exe')[sys.platform == 'win32']
++ if zxing_dir:
++ zxing_executable = os.path.join(zxing_dir, zxing_executable)
++ print 'Decoding barcodes from PNG files with %s...' % zxing_executable
++diff -up comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_encoder.py.python3 comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_encoder.py
++--- comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_encoder.py.python3 2014-07-17 18:05:43.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/barcode_encoder.py 2014-10-24 11:41:35.475880159 -0600
++@@ -58,7 +58,7 @@ def generate_upca_barcodes(number_of_bar
++ try:
++ helper_functions.run_shell_command(
++ command, fail_msg=('Error during barcode %s generation' % content))
++- except helper_functions.HelperError as err:
+++ except helper_functions.HelperError, err:
++ print >> sys.stderr, err
++ errors = True
++ return not errors
++@@ -110,7 +110,7 @@ def _convert_to_yuv_and_delete(output_di
++ command, fail_msg=('Error during PNG to YUV conversion of %s' %
++ file_name))
++ os.remove(file_name)
++- except helper_functions.HelperError as err:
+++ except helper_functions.HelperError, err:
++ print >> sys.stderr, err
++ return False
++ return True
++@@ -153,7 +153,7 @@ def _add_to_file_and_delete(output_file,
++ input_file.close()
++ try:
++ os.remove(file_name)
++- except OSError as e:
+++ except OSError, e:
++ print >> sys.stderr, 'Error deleting file %s.\nError: %s' % (file_name, e)
++ return False
++ return True
++@@ -330,8 +330,7 @@ def _main():
++ --output_yuv=<path and name_of_output_file>
++ """
++ options = _parse_args()
++- # The barcodes with will be different than the base frame width only if
++- # explicitly specified at the command line.
+++ # The barcodes with will be different than the base frame width only if # explicitly specified at the command line.
++ if options.barcode_width == _DEFAULT_BARCODE_WIDTH:
++ options.barcode_width = options.base_frame_width
++ # If the user provides a value for the barcodes YUV video file, we will keep
++diff -up comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/build_zxing.py.python3 comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/build_zxing.py
++--- comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/build_zxing.py.python3 2014-07-17 18:05:43.000000000 -0600
+++++ comm-esr31/mozilla/media/webrtc/trunk/webrtc/tools/barcode_tools/build_zxing.py 2014-10-24 11:41:35.475880159 -0600
++@@ -27,7 +27,7 @@ def run_ant_build_command(path_to_ant_bu
++ if process.returncode != 0:
++ print >> sys.stderr, 'Failed to execute: %s' % ' '.join(cmd)
++ return process.returncode
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ print >> sys.stderr, 'Failed to execute: %s.\nCause: %s' % (' '.join(cmd),
++ e)
++ return -1
++diff -up comm-esr31/mozilla/mobile/android/debug_sign_tool.py.python3 comm-esr31/mozilla/mobile/android/debug_sign_tool.py
++--- comm-esr31/mozilla/mobile/android/debug_sign_tool.py.python3 2014-07-17 18:05:44.000000000 -0600
+++++ comm-esr31/mozilla/mobile/android/debug_sign_tool.py 2014-10-24 11:41:35.476880155 -0600
++@@ -55,7 +55,7 @@ class DebugKeystore:
++ subprocess.check_call(args)
++ else:
++ subprocess.check_output(args)
++- except OSError as ex:
+++ except OSError, ex:
++ if ex.errno != errno.ENOENT:
++ raise
++ raise Exception("Could not find executable '%s'" % args[0])
++@@ -72,12 +72,12 @@ class DebugKeystore:
++ contains = True
++ try:
++ self._check(args)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ contains = False
++ if self.verbose:
++ log.info('Keystore %s %s alias %s' %
++ (self.keystore,
++- 'contains' if contains else 'does not contain',
+++ ('does not contain', 'contains')[contains],
++ self.alias))
++ return contains
++
++@@ -85,7 +85,7 @@ class DebugKeystore:
++ try:
++ path = os.path.dirname(self.keystore)
++ os.makedirs(path)
++- except OSError as exception:
+++ except OSError, exception:
++ if exception.errno != errno.EEXIST:
++ raise
++
++@@ -167,7 +167,7 @@ def main():
++ if args.force:
++ try:
++ keystore.create_alias_in_keystore()
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ log.error('Failed to force-create alias %s in keystore %s' %
++ (keystore.alias, keystore.keystore))
++ log.error(e)
++@@ -176,7 +176,7 @@ def main():
++ for apk in args.apks:
++ try:
++ keystore.sign(apk)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ log.error('Failed to sign %s', apk)
++ log.error(e)
++ return 1
++diff -up comm-esr31/mozilla/mozglue/build/fixcrt.py.python3 comm-esr31/mozilla/mozglue/build/fixcrt.py
++--- comm-esr31/mozilla/mozglue/build/fixcrt.py.python3 2014-07-17 18:05:45.000000000 -0600
+++++ comm-esr31/mozilla/mozglue/build/fixcrt.py 2014-10-24 11:41:35.476880155 -0600
++@@ -2,13 +2,16 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++
++ with open('crtdll.obj', 'rb') as infile:
++ data = infile.read()
++- with open('crtdll_fixed.obj', 'wb') as outfile:
+++ outfile = open('crtdll_fixed.obj', 'wb')
+++ if 1:
++ # for Win32
++ data = data.replace('__imp__free', '__imp__frex')
++ # for Win64
++ data = data.replace('__imp_free', '__imp_frex')
++ outfile.write(data)
+++ outfile.close()
+++
++diff -up comm-esr31/mozilla/netwerk/protocol/http/make_incoming_tables.py.python3 comm-esr31/mozilla/netwerk/protocol/http/make_incoming_tables.py
++--- comm-esr31/mozilla/netwerk/protocol/http/make_incoming_tables.py.python3 2014-07-17 18:05:46.000000000 -0600
+++++ comm-esr31/mozilla/netwerk/protocol/http/make_incoming_tables.py 2014-10-24 11:41:35.476880155 -0600
++@@ -84,7 +84,7 @@ def output_table(table, name_suffix=''):
++ elif t is not None:
++ output_table(t, '%s_%s' % (name_suffix, i))
++
++- tablename = 'HuffmanIncoming%s' % (name_suffix if name_suffix else 'Root',)
+++ tablename = 'HuffmanIncoming%s' % (('Root', name_suffix)[name_suffix],)
++ entriestable = tablename.replace('HuffmanIncoming', 'HuffmanIncomingEntries')
++ sys.stdout.write('static HuffmanIncomingEntry %s[] = {\n' % (entriestable,))
++ prefix_len = 0
++diff -up comm-esr31/mozilla/other-licenses/ply/ply/yacc.py.python3 comm-esr31/mozilla/other-licenses/ply/ply/yacc.py
++--- comm-esr31/mozilla/other-licenses/ply/ply/yacc.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/other-licenses/ply/ply/yacc.py 2014-10-24 11:41:35.477880151 -0600
++@@ -98,7 +98,7 @@ else:
++ try:
++ MAXINT = sys.maxint
++ except AttributeError:
++- MAXINT = sys.maxsize
+++ MAXINT = sys.maxint
++
++ # Python 2.x/3.0 compatibility.
++ def load_ply_lex():
++@@ -501,8 +501,7 @@ class LRParser:
++ #
++ # In addition to pushing the error token, we call call
++ # the user defined p_error() function if this is the
++- # first syntax error. This function is only called if
++- # errorcount == 0.
+++ # first syntax error. This function is only called if # errorcount == 0.
++ if errorcount == 0 or self.errorok:
++ errorcount = error_count
++ self.errorok = 0
++@@ -774,8 +773,7 @@ class LRParser:
++ #
++ # In addition to pushing the error token, we call call
++ # the user defined p_error() function if this is the
++- # first syntax error. This function is only called if
++- # errorcount == 0.
+++ # first syntax error. This function is only called if # errorcount == 0.
++ if errorcount == 0 or self.errorok:
++ errorcount = error_count
++ self.errorok = 0
++@@ -1029,8 +1027,7 @@ class LRParser:
++ #
++ # In addition to pushing the error token, we call call
++ # the user defined p_error() function if this is the
++- # first syntax error. This function is only called if
++- # errorcount == 0.
+++ # first syntax error. This function is only called if # errorcount == 0.
++ if errorcount == 0 or self.errorok:
++ errorcount = error_count
++ self.errorok = 0
++diff -up comm-esr31/mozilla/python/blessings/blessings/__init__.py.python3 comm-esr31/mozilla/python/blessings/blessings/__init__.py
++--- comm-esr31/mozilla/python/blessings/blessings/__init__.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/blessings/blessings/__init__.py 2014-10-24 11:41:35.477880151 -0600
++@@ -1,4 +1,4 @@
++-from collections import defaultdict
+++from mycollections import defaultdict
++ import curses
++ from curses import tigetstr, tigetnum, setupterm, tparm
++ from fcntl import ioctl
++@@ -73,9 +73,11 @@ class Terminal(object):
++ if stream is None:
++ stream = sys.__stdout__
++ try:
++- stream_descriptor = (stream.fileno() if hasattr(stream, 'fileno')
++- and callable(stream.fileno)
++- else None)
+++ stream_descriptor = None
+++ if hasattr(stream, 'fileno') and callable(stream.fileno):
+++ stream_descriptor = (stream.fileno())
+++ else:
+++ stream_descriptor = (None)
++ except IOUnsupportedOperation:
++ stream_descriptor = None
++
++@@ -85,9 +87,11 @@ class Terminal(object):
++ # The desciptor to direct terminal initialization sequences to.
++ # sys.__stdout__ seems to always have a descriptor of 1, even if output
++ # is redirected.
++- self._init_descriptor = (sys.__stdout__.fileno()
++- if stream_descriptor is None
++- else stream_descriptor)
+++ self._init_descriptor = None
+++ if stream_descriptor is None:
+++ self._init_descriptor = (sys.__stdout__.fileno())
+++ else:
+++ self._init_descriptor = (stream_descriptor)
++ if self._does_styling:
++ # Make things like tigetstr() work. Explicit args make setupterm()
++ # work even when -s is passed to nosetests. Lean toward sending
++@@ -154,7 +158,11 @@ class Terminal(object):
++ Return values are always Unicode.
++
++ """
++- resolution = self._resolve_formatter(attr) if self._does_styling else NullCallableString()
+++ resolution = None
+++ if self._does_styling:
+++ resolution = self._resolve_formatter(attr)
+++ else:
+++ resolution = NullCallableString()
++ setattr(self, attr, resolution) # Cache capability codes.
++ return resolution
++
++@@ -200,11 +208,13 @@ class Terminal(object):
++ there, then return the cursor to its original position::
++
++ term = Terminal()
++- with term.location(2, 5):
+++ term.location(2, 5).__enter__()
+++ if 1:
++ print 'Hello, world!'
++ for x in xrange(10):
++ print 'I can do it %i times!' % x
++
+++ term.location(2, 5).__exit__(0, 0, 0)
++ Specify ``x`` to move to a certain column, ``y`` to move to a certain
++ row, or both.
++
++@@ -256,7 +266,10 @@ class Terminal(object):
++ # access to it.
++ colors = tigetnum('colors') # Returns -1 if no color support, -2 if no such cap.
++ #self.__dict__['colors'] = ret # Cache it. It's not changing. (Doesn't work.)
++- return colors if colors >= 0 else 0
+++ if colors >= 0:
+++ return colors
+++ else:
+++ return 0
++
++ def _resolve_formatter(self, attr):
++ """Resolve a sugary or plain capability name, color, or compound formatting function name into a callable capability."""
++@@ -297,11 +310,18 @@ class Terminal(object):
++ # yellow when a terminal supports setf/setb rather than setaf/setab?
++ # I'll be blasted if I can find any documentation. The following
++ # assumes it does.
++- color_cap = (self._background_color if 'on_' in color else
++- self._foreground_color)
+++ color_cap = None
+++ if 'on_' in color:
+++ color_cap = (self._background_color)
+++ else:
+++ color_cap = (self._foreground_color)
++ # curses constants go up to only 7, so add an offset to get at the
++ # bright colors at 8-15:
++- offset = 8 if 'bright_' in color else 0
+++ offset = None
+++ if 'bright_' in color:
+++ offset = 8
+++ else:
+++ offset = 0
++ base_color = color.rsplit('_', 1)[-1]
++ return self._formatting_string(
++ color_cap(getattr(curses, 'COLOR_' + base_color.upper()) + offset))
++@@ -353,8 +373,7 @@ class ParametrizingString(unicode):
++ # 3. However, appear to be a plain Unicode string otherwise so
++ # concats work.
++ parametrized = tparm(self.encode('utf-8'), *args).decode('utf-8')
++- return (parametrized if self._normal is None else
++- FormattingString(parametrized, self._normal))
+++ return ((FormattingString(parametrized, self._normal), parametrized)[self._normal is None])
++ except curses.error:
++ # Catch "must call (at least) setupterm() first" errors, as when
++ # running simply `nosetests` (without progressive) on nose-
++diff -up comm-esr31/mozilla/python/blessings/blessings/tests.py.python3 comm-esr31/mozilla/python/blessings/blessings/tests.py
++--- comm-esr31/mozilla/python/blessings/blessings/tests.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/blessings/blessings/tests.py 2014-10-24 11:41:35.477880151 -0600
++@@ -9,7 +9,7 @@ All we require from the host machine is
++ xterm-256color exists.
++
++ """
++-from __future__ import with_statement # Make 2.5-compatible
+++ # Make 2.5-compatible
++ from curses import tigetstr, tparm
++ from functools import partial
++ from StringIO import StringIO
++@@ -83,9 +83,11 @@ def test_location():
++ """Make sure ``location()`` does what it claims."""
++ t = TestTerminal(stream=StringIO(), force_styling=True)
++
++- with t.location(3, 4):
+++ t.location(3, 4).__enter__()
+++ if 1:
++ t.stream.write(u'hi')
++
+++ t.location(3, 4).__exit__(0, 0, 0)
++ eq_(t.stream.getvalue(), unicode_cap('sc') +
++ unicode_parm('cup', 4, 3) +
++ u'hi' +
++@@ -95,8 +97,10 @@ def test_location():
++ def test_horizontal_location():
++ """Make sure we can move the cursor horizontally without changing rows."""
++ t = TestTerminal(stream=StringIO(), force_styling=True)
++- with t.location(x=5):
+++ t.location(x=5).__enter__()
+++ if 1:
++ pass
+++ t.location(x=5).__exit__(0, 0, 0)
++ eq_(t.stream.getvalue(), unicode_cap('sc') +
++ unicode_parm('hpa', 5) +
++ unicode_cap('rc'))
++diff -up comm-esr31/mozilla/python/codegen/makeutils.py.python3 comm-esr31/mozilla/python/codegen/makeutils.py
++--- comm-esr31/mozilla/python/codegen/makeutils.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/codegen/makeutils.py 2014-10-24 11:41:35.477880151 -0600
++@@ -17,11 +17,12 @@ def writeMakeDependOutput(filename):
++ if dir and not os.path.exists(dir):
++ try:
++ os.makedirs(dir)
++- except OSError as error:
+++ except OSError, error:
++ if error.errno != errno.EEXIST:
++ raise
++
++- with open(filename, 'w') as f:
+++ f = open(filename, 'w')
+++ if 1:
++ if len(targets) > 0:
++ f.write("%s:" % makeQuote(targets[0]))
++ for filename in dependencies:
++@@ -32,3 +33,5 @@ def writeMakeDependOutput(filename):
++ for filename in dependencies:
++ f.write('%s:\n' % filename)
++
+++ f.close()
+++
++diff -up comm-esr31/mozilla/python/configobj/configobj.py.python3 comm-esr31/mozilla/python/configobj/configobj.py
++--- comm-esr31/mozilla/python/configobj/configobj.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/configobj/configobj.py 2014-10-24 11:41:35.478880146 -0600
++@@ -587,8 +587,7 @@ class Section(dict):
++ (We have to special case 'Section' instances - which are also dicts)
++
++ Keys must be strings.
++- Values need only be strings (or lists of strings) if
++- ``main.stringify`` is set.
+++ Values need only be strings (or lists of strings) if ``main.stringify`` is set.
++
++ ``unrepr`` must be set when setting a value to a dictionary, without
++ creating a new sub-section.
++diff -up comm-esr31/mozilla/python/mach_commands.py.python3 comm-esr31/mozilla/python/mach_commands.py
++--- comm-esr31/mozilla/python/mach_commands.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach_commands.py 2014-10-24 11:41:35.478880146 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import argparse
++ import glob
++@@ -106,4 +110,7 @@ class MachCommands(MachCommandBase):
++ if stop and return_code > 0:
++ return 1
++
++- return 0 if return_code == 0 else 1
+++ if return_code == 0:
+++ return 0
+++ else:
+++ return 1
++diff -up comm-esr31/mozilla/python/mach/mach/base.py.python3 comm-esr31/mozilla/python/mach/mach/base.py
++--- comm-esr31/mozilla/python/mach/mach/base.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/base.py 2014-10-24 11:41:35.478880146 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++
++ class CommandContext(object):
++diff -up comm-esr31/mozilla/python/mach/mach/commands/commandinfo.py.python3 comm-esr31/mozilla/python/mach/mach/commands/commandinfo.py
++--- comm-esr31/mozilla/python/mach/mach/commands/commandinfo.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/commands/commandinfo.py 2014-10-24 11:41:35.478880146 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ from mach.decorators import (
++ CommandProvider,
++diff -up comm-esr31/mozilla/python/mach/mach/commands/settings.py.python3 comm-esr31/mozilla/python/mach/mach/commands/settings.py
++--- comm-esr31/mozilla/python/mach/mach/commands/settings.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/commands/settings.py 2014-10-24 11:41:35.478880146 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ from textwrap import TextWrapper
++
++diff -up comm-esr31/mozilla/python/mach/mach/config.py.python3 comm-esr31/mozilla/python/mach/mach/config.py
++--- comm-esr31/mozilla/python/mach/mach/config.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/config.py 2014-10-24 11:41:35.479880142 -0600
++@@ -25,7 +25,7 @@ msgfmt binary to perform this conversion
++ can be done via the write_pot() of ConfigSettings.
++ """
++
++-from __future__ import unicode_literals
+++
++
++ import collections
++ import gettext
++@@ -93,7 +93,7 @@ class BooleanType(ConfigType):
++
++ @staticmethod
++ def to_config(value):
++- return 'true' if value else 'false'
+++ return ('false', 'true')[value]
++
++
++ class IntegerType(ConfigType):
++@@ -227,7 +227,11 @@ class ConfigProvider(object):
++ raise Exception('Setting has already been registered: %s.%s' % (
++ section, option))
++
++- domain = domain if domain is not None else section
+++ domain = None
+++ if domain is not None:
+++ domain = domain
+++ else:
+++ domain = section
++
++ meta = {
++ 'short': '%s.short' % option,
++diff -up comm-esr31/mozilla/python/mach/mach/decorators.py.python3 comm-esr31/mozilla/python/mach/mach/decorators.py
++--- comm-esr31/mozilla/python/mach/mach/decorators.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/decorators.py 2014-10-24 11:41:35.479880142 -0600
++@@ -2,19 +2,19 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import collections
++ import inspect
++ import types
++
++-from .base import (
+++from base import (
++ MachError,
++ MethodHandler
++ )
++
++-from .config import ConfigProvider
++-from .registrar import Registrar
+++from config import ConfigProvider
+++from registrar import Registrar
++
++
++ def CommandProvider(cls):
++diff -up comm-esr31/mozilla/python/mach/mach/dispatcher.py.python3 comm-esr31/mozilla/python/mach/mach/dispatcher.py
++--- comm-esr31/mozilla/python/mach/mach/dispatcher.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/dispatcher.py 2014-10-24 11:41:35.479880142 -0600
++@@ -2,14 +2,14 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import argparse
++ import sys
++
++ from operator import itemgetter
++
++-from .base import (
+++from base import (
++ NoCommandError,
++ UnknownCommandError,
++ UnrecognizedArgumentError,
++diff -up comm-esr31/mozilla/python/mach/mach/logging.py.python3 comm-esr31/mozilla/python/mach/mach/logging.py
++--- comm-esr31/mozilla/python/mach/mach/logging.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/logging.py 2014-10-24 11:41:35.479880142 -0600
++@@ -6,18 +6,25 @@
++ # support for a structured logging framework built on top of Python's built-in
++ # logging framework.
++
++-from __future__ import absolute_import, unicode_literals
+++
++
++ try:
++ import blessings
++ except ImportError:
++ blessings = None
++
++-import json
++-import logging
+++import simplejson as json
+++import rhrebase
+++logging = rhrebase.import_non_local('logging')
+++
+++import logging as moz_logging
++ import sys
++ import time
++
+++class NullHandler(logging.Handler):
+++ def emit(self, record):
+++ pass
+++logging.NullHandler = NullHandler
++
++ def format_seconds(total):
++ """Format number of seconds to MM:SS.DD form."""
++@@ -145,7 +152,7 @@ class LoggingManager(object):
++ # Installing NullHandler on the root logger ensures that *all* log
++ # messages have at least one handler. This prevents Python from
++ # complaining about "no handlers could be found for logger XXX."
++- self.root_logger.addHandler(logging.NullHandler())
+++ #FIXME? self.root_logger.addHandler(NullHandler())
++
++ self.mach_logger = logging.getLogger('mach')
++ self.mach_logger.setLevel(logging.DEBUG)
++@@ -175,7 +182,7 @@ class LoggingManager(object):
++ """Enable JSON logging on the specified file object."""
++
++ # Configure the consumer of structured messages.
++- handler = logging.StreamHandler(stream=fh)
+++ handler = logging.StreamHandler(fh)
++ handler.setFormatter(StructuredJSONFormatter())
++ handler.setLevel(logging.DEBUG)
++
++@@ -197,7 +204,7 @@ class LoggingManager(object):
++ write_interval=write_interval, write_times=write_times)
++ formatter.set_terminal(self.terminal)
++
++- handler = logging.StreamHandler(stream=fh)
+++ handler = logging.StreamHandler(fh)
++ handler.setFormatter(formatter)
++ handler.setLevel(level)
++
++diff -up comm-esr31/mozilla/python/mach/mach/main.py.python3 comm-esr31/mozilla/python/mach/mach/main.py
++--- comm-esr31/mozilla/python/mach/mach/main.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/main.py 2014-10-24 11:41:35.480880138 -0600
++@@ -5,7 +5,7 @@
++ # This module provides functionality for the command-line build tool
++ # (mach). It is packaged as a module because everything is a library.
++
++-from __future__ import absolute_import, print_function, unicode_literals
+++, print_function, unicode_literals
++ from collections import Iterable
++
++ import argparse
++@@ -18,7 +18,7 @@ import traceback
++ import uuid
++ import sys
++
++-from .base import (
+++from base import (
++ CommandContext,
++ MachError,
++ NoCommandError,
++@@ -26,16 +26,16 @@ from .base import (
++ UnrecognizedArgumentError,
++ )
++
++-from .decorators import (
+++from decorators import (
++ CommandArgument,
++ CommandProvider,
++ Command,
++ )
++
++-from .config import ConfigSettings
++-from .dispatcher import CommandAction
++-from .logging import LoggingManager
++-from .registrar import Registrar
+++from config import ConfigSettings
+++from dispatcher import CommandAction
+++from logging import LoggingManager
+++from registrar import Registrar
++
++
++
++@@ -288,9 +288,16 @@ To see more help for a specific command,
++ # up with UnicodeEncodeError as soon as it encounters a non-ASCII
++ # character in a unicode instance. We simply install a wrapper around
++ # the streams and restore once we have finished.
++- stdin = sys.stdin if stdin is None else stdin
++- stdout = sys.stdout if stdout is None else stdout
++- stderr = sys.stderr if stderr is None else stderr
+++ stdin = (sys.stdin, stdin)[stdin]
+++ stdout = (sys.stdout, stdout)[stdout]
+++ stderr = (sys.stderr, stderr)[stderr]
+++ #else:
+++ # stdin = stdout
+++ #stderr = None
+++ #if stderr is None:
+++ # stderr = sys.stderr
+++ #else:
+++ # stderr = stderr
++
++ orig_stdin = sys.stdin
++ orig_stdout = sys.stdout
++@@ -315,7 +322,7 @@ To see more help for a specific command,
++ print('mach interrupted by signal or user action. Stopping.')
++ return 1
++
++- except Exception as e:
+++ except Exception, e:
++ # _run swallows exceptions in invoked handlers and converts them to
++ # a proper exit code. So, the only scenario where we should get an
++ # exception here is if _run itself raises. If _run raises, that's a
++@@ -359,10 +366,10 @@ To see more help for a specific command,
++ except NoCommandError:
++ print(NO_COMMAND_ERROR)
++ return 1
++- except UnknownCommandError as e:
+++ except UnknownCommandError, e:
++ print(UNKNOWN_COMMAND_ERROR % (e.verb, e.command))
++ return 1
++- except UnrecognizedArgumentError as e:
+++ except UnrecognizedArgumentError, e:
++ print(UNRECOGNIZED_ARGUMENT_ERROR % (e.command,
++ ' '.join(e.arguments)))
++ return 1
++@@ -421,9 +428,9 @@ To see more help for a specific command,
++ assert isinstance(result, (int, long))
++
++ return result
++- except KeyboardInterrupt as ki:
+++ except KeyboardInterrupt, ki:
++ raise ki
++- except Exception as e:
+++ except Exception, e:
++ exc_type, exc_value, exc_tb = sys.exc_info()
++
++ # The first frame is us and is never used.
++diff -up comm-esr31/mozilla/python/mach/mach/mixin/logging.py.python3 comm-esr31/mozilla/python/mach/mach/mixin/logging.py
++--- comm-esr31/mozilla/python/mach/mach/mixin/logging.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/mixin/logging.py 2014-10-24 11:41:35.480880138 -0600
++@@ -2,10 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import absolute_import, unicode_literals
++
++-import logging
++
+++#import logging
+++from rhrebase import import_non_local
+++logging = import_non_local('logging')
++
++ class LoggingMixin(object):
++ """Provides functionality to control logging."""
++@@ -50,6 +51,7 @@ class LoggingMixin(object):
++ self.log(logging.DEBUG, 'login', {'username': 'johndoe'},
++ 'User login: {username}')
++ """
++- self._logger.log(level, format_str,
++- extra={'action': action, 'params': params})
+++ self._logger.log(level, format_str)
+++ #extra={'action': action, 'params': params})
+++ #extra={'action': action, 'params': params})
++
++diff -up comm-esr31/mozilla/python/mach/mach/mixin/process.py.python3 comm-esr31/mozilla/python/mach/mach/mixin/process.py
++--- comm-esr31/mozilla/python/mach/mach/mixin/process.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/mixin/process.py 2014-10-24 11:41:35.480880138 -0600
++@@ -4,16 +4,18 @@
++
++ # This module provides mixins to perform process execution.
++
++-from __future__ import absolute_import, unicode_literals
++
++-import logging
+++
+++#import logging
+++from rhrebase import import_non_local
+++logging = import_non_local('logging')
++ import os
++ import subprocess
++ import sys
++
++ from mozprocess.processhandler import ProcessHandlerMixin
++
++-from .logging import LoggingMixin
+++from logging import LoggingMixin
++
++
++ # Perform detection of operating system environment. This is used by command
++@@ -36,7 +38,7 @@ if os.environ.get('MSYSTEM', None) == 'M
++ if not _current_shell.lower().endswith('.exe'):
++ _current_shell += '.exe'
++
++-
+++#print dir(logging)
++ class ProcessExecutionMixin(LoggingMixin):
++ """Mix-in that provides process execution functionality."""
++
++diff -up comm-esr31/mozilla/python/mach/mach/registrar.py.python3 comm-esr31/mozilla/python/mach/mach/registrar.py
++--- comm-esr31/mozilla/python/mach/mach/registrar.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/registrar.py 2014-10-24 11:41:35.480880138 -0600
++@@ -2,9 +2,9 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
++
++-from .base import MachError
+++
+++from base import MachError
++
++
++ class MachRegistrar(object):
++diff -up comm-esr31/mozilla/python/mach/mach/terminal.py.python3 comm-esr31/mozilla/python/mach/mach/terminal.py
++--- comm-esr31/mozilla/python/mach/mach/terminal.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/terminal.py 2014-10-24 11:41:35.480880138 -0600
++@@ -8,7 +8,11 @@ All the terminal interaction code is con
++ one place, away from code that is commonly looked at.
++ """
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import logging
++ import sys
++diff -up comm-esr31/mozilla/python/mach/mach/test/common.py.python3 comm-esr31/mozilla/python/mach/mach/test/common.py
++--- comm-esr31/mozilla/python/mach/mach/test/common.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/common.py 2014-10-24 11:41:35.481880134 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from StringIO import StringIO
++ import os
++diff -up comm-esr31/mozilla/python/mach/mach/test/providers/basic.py.python3 comm-esr31/mozilla/python/mach/mach/test/providers/basic.py
++--- comm-esr31/mozilla/python/mach/mach/test/providers/basic.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/providers/basic.py 2014-10-24 11:41:35.481880134 -0600
++@@ -1,7 +1,7 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import unicode_literals
+++
++
++ from mach.decorators import (
++ CommandProvider,
++diff -up comm-esr31/mozilla/python/mach/mach/test/providers/conditions_invalid.py.python3 comm-esr31/mozilla/python/mach/mach/test/providers/conditions_invalid.py
++--- comm-esr31/mozilla/python/mach/mach/test/providers/conditions_invalid.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/providers/conditions_invalid.py 2014-10-24 11:41:35.481880134 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from mach.decorators import (
++ CommandProvider,
++diff -up comm-esr31/mozilla/python/mach/mach/test/providers/conditions.py.python3 comm-esr31/mozilla/python/mach/mach/test/providers/conditions.py
++--- comm-esr31/mozilla/python/mach/mach/test/providers/conditions.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/providers/conditions.py 2014-10-24 11:41:35.481880134 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from mach.decorators import (
++ CommandProvider,
++diff -up comm-esr31/mozilla/python/mach/mach/test/providers/throw.py.python3 comm-esr31/mozilla/python/mach/mach/test/providers/throw.py
++--- comm-esr31/mozilla/python/mach/mach/test/providers/throw.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/providers/throw.py 2014-10-24 11:41:35.481880134 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import time
++
++diff -up comm-esr31/mozilla/python/mach/mach/test/test_conditions.py.python3 comm-esr31/mozilla/python/mach/mach/test/test_conditions.py
++--- comm-esr31/mozilla/python/mach/mach/test/test_conditions.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/test_conditions.py 2014-10-24 11:41:35.481880134 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++diff -up comm-esr31/mozilla/python/mach/mach/test/test_config.py.python3 comm-esr31/mozilla/python/mach/mach/test/test_config.py
++--- comm-esr31/mozilla/python/mach/mach/test/test_config.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/test_config.py 2014-10-24 11:41:35.482880130 -0600
++@@ -1,7 +1,7 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import unicode_literals
+++
++
++ import sys
++ import unittest
++@@ -67,10 +67,12 @@ class TestConfigProvider(unittest.TestCa
++ self.assertIn('baz', s['foo'])
++
++ def test_duplicate_option(self):
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ ProviderDuplicate.register_settings()
++
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ class Provider2(ConfigProvider):
++ @classmethod
++ def _register_settings(cls):
++@@ -117,56 +119,76 @@ class TestConfigSettings(unittest.TestCa
++ a = s.a
++
++ # Assigning an undeclared setting raises.
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ a.undefined = True
++
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ a['undefined'] = True
++
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
++ # Basic type validation.
++ a.string = 'foo'
++ a.string = 'foo'
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ a.string = False
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ a.boolean = True
++ a.boolean = False
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ a.boolean = 'foo'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ a.pos_int = 5
++ a.pos_int = 0
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ a.pos_int = -1
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ a.pos_int = 'foo'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ a.int = 5
++ a.int = 0
++ a.int = -5
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ a.int = 1.24
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ a.int = 'foo'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ a.abs_path = '/home/gps'
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ a.abs_path = 'home/gps'
++
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
++ a.rel_path = 'home/gps'
++ a.rel_path = './foo/bar'
++ a.rel_path = 'foo.c'
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ a.rel_path = '/foo/bar'
++
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
++ a.path = '/home/gps'
++ a.path = 'foo.c'
++ a.path = 'foo/bar'
++diff -up comm-esr31/mozilla/python/mach/mach/test/test_entry_point.py.python3 comm-esr31/mozilla/python/mach/mach/test/test_entry_point.py
++--- comm-esr31/mozilla/python/mach/mach/test/test_entry_point.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/test_entry_point.py 2014-10-24 11:41:35.482880130 -0600
++@@ -1,7 +1,7 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import unicode_literals
+++
++
++ import imp
++ import os
++@@ -43,9 +43,11 @@ class TestEntryPoints(TestBase):
++
++ mock.return_value = [Entry(['providers'])]
++ # Mach error raised due to conditions_invalid.py
++- with self.assertRaises(MachError):
+++ self.assertRaises(MachError).__enter__()
+++ if 1:
++ self._run_mach()
++
+++ self.assertRaises(MachError).__exit__(0, 0, 0)
++ @patch('pkg_resources.iter_entry_points')
++ def test_load_entry_point_from_file(self, mock):
++ mock.return_value = [Entry([os.path.join('providers', 'basic.py')])]
++diff -up comm-esr31/mozilla/python/mach/mach/test/test_error_output.py.python3 comm-esr31/mozilla/python/mach/mach/test/test_error_output.py
++--- comm-esr31/mozilla/python/mach/mach/test/test_error_output.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/test_error_output.py 2014-10-24 11:41:35.482880130 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from mach.main import (
++ COMMAND_ERROR,
++diff -up comm-esr31/mozilla/python/mach/mach/test/test_logger.py.python3 comm-esr31/mozilla/python/mach/mach/test/test_logger.py
++--- comm-esr31/mozilla/python/mach/mach/test/test_logger.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mach/mach/test/test_logger.py 2014-10-24 11:41:35.482880130 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import absolute_import, unicode_literals
+++
++
++ import logging
++ import time
++diff -up comm-esr31/mozilla/python/mock-1.0.0/mock.py.python3 comm-esr31/mozilla/python/mock-1.0.0/mock.py
++--- comm-esr31/mozilla/python/mock-1.0.0/mock.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mock-1.0.0/mock.py 2014-10-24 11:41:35.483880125 -0600
++@@ -871,8 +871,7 @@ class NonCallableMock(Base):
++ """assert the mock has been called with the specified arguments.
++
++ The assert passes if the mock has *ever* been called, unlike
++- `assert_called_with` and `assert_called_once_with` that only pass if
++- the call is the most recent one."""
+++ `assert_called_with` and `assert_called_once_with` that only pass if the call is the most recent one."""
++ kall = call(*args, **kwargs)
++ if kall not in self.call_args_list:
++ expected_string = self._format_mock_call_signature(args, kwargs)
++@@ -1438,9 +1437,11 @@ def _patch_multiple(target, spec=None, c
++ patched (either as an object or a string to fetch the object by importing)
++ and keyword arguments for the patches::
++
++- with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):
+++ patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two').__enter__()
+++ if 1:
++ ...
++
+++ patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two').__exit__(0, 0, 0)
++ Use `DEFAULT` as the value if you want `patch.multiple` to create
++ mocks for you. In this case the created mocks are passed into a decorated
++ function by keyword, and a dictionary is returned when `patch.multiple` is
++@@ -1517,8 +1518,7 @@ def patch(
++ then the mock with be created with a spec from the object being replaced.
++ All attributes of the mock will also have the spec of the corresponding
++ attribute of the object being replaced. Methods and functions being
++- mocked will have their arguments checked and will raise a `TypeError` if
++- they are called with the wrong signature. For mocks replacing a class,
+++ mocked will have their arguments checked and will raise a `TypeError` if they are called with the wrong signature. For mocks replacing a class,
++ their return value (the 'instance') will have the same spec as the class.
++
++ Instead of `autospec=True` you can pass `autospec=some_object` to use an
++@@ -1578,9 +1578,11 @@ class _patch_dict(object):
++ `patch.dict` can also be called with arbitrary keyword arguments to set
++ values in the dictionary::
++
++- with patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()):
+++ patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()).__enter__()
+++ if 1:
++ ...
++
+++ patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()).__exit__(0, 0, 0)
++ `patch.dict` can be used as a context manager, decorator or class
++ decorator. When used as a class decorator `patch.dict` honours
++ `patch.TEST_PREFIX` for choosing which methods to wrap.
++diff -up comm-esr31/mozilla/python/mock-1.0.0/tests/support_with.py.python3 comm-esr31/mozilla/python/mock-1.0.0/tests/support_with.py
++--- comm-esr31/mozilla/python/mock-1.0.0/tests/support_with.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mock-1.0.0/tests/support_with.py 2014-10-24 11:41:35.483880125 -0600
++@@ -1,4 +1,4 @@
++-from __future__ import with_statement
+++
++
++ import sys
++
++@@ -88,6 +88,8 @@ except ImportError:
++
++ def examine_warnings(func):
++ def wrapper():
++- with catch_warnings(record=True) as ws:
+++ ws = catch_warnings(record=True).__enter__()
+++ if 1:
++ func(ws)
+++ ws.__exit__(0, 0, 0)
++ return wrapper
++diff -up comm-esr31/mozilla/python/mock-1.0.0/tests/testmagicmethods.py.python3 comm-esr31/mozilla/python/mock-1.0.0/tests/testmagicmethods.py
++--- comm-esr31/mozilla/python/mock-1.0.0/tests/testmagicmethods.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mock-1.0.0/tests/testmagicmethods.py 2014-10-24 11:41:35.483880125 -0600
++@@ -329,7 +329,7 @@ class TestMockingMagicMethods(unittest2.
++ else:
++ # in Python 3 oct and hex use __index__
++ # so these tests are for __index__ in py3k
++- self.assertEqual(oct(mock), '0o1')
+++ self.assertEqual(oct(mock), '01')
++ self.assertEqual(hex(mock), '0x1')
++ # how to test __sizeof__ ?
++
++diff -up comm-esr31/mozilla/python/mock-1.0.0/tests/_testwith.py.python3 comm-esr31/mozilla/python/mock-1.0.0/tests/_testwith.py
++--- comm-esr31/mozilla/python/mock-1.0.0/tests/_testwith.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mock-1.0.0/tests/_testwith.py 2014-10-24 11:41:35.483880125 -0600
++@@ -2,7 +2,7 @@
++ # E-mail: fuzzyman AT voidspace DOT org DOT uk
++ # http://www.voidspace.org.uk/python/mock/
++
++-from __future__ import with_statement
+++
++
++ from tests.support import unittest2, is_instance
++
++@@ -18,16 +18,20 @@ something_else = sentinel.SomethingElse
++ class WithTest(unittest2.TestCase):
++
++ def test_with_statement(self):
++- with patch('tests._testwith.something', sentinel.Something2):
+++ patch('tests._testwith.something', sentinel.Something2).__enter__()
+++ if 1:
++ self.assertEqual(something, sentinel.Something2, "unpatched")
+++ patch('tests._testwith.something', sentinel.Something2).__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something)
++
++
++ def test_with_statement_exception(self):
++ try:
++- with patch('tests._testwith.something', sentinel.Something2):
+++ patch('tests._testwith.something', sentinel.Something2).__enter__()
+++ if 1:
++ self.assertEqual(something, sentinel.Something2, "unpatched")
++ raise Exception('pow')
+++ patch('tests._testwith.something', sentinel.Something2).__exit__(0, 0, 0)
++ except Exception:
++ pass
++ else:
++@@ -36,10 +40,12 @@ class WithTest(unittest2.TestCase):
++
++
++ def test_with_statement_as(self):
++- with patch('tests._testwith.something') as mock_something:
+++ mock_something = patch('tests._testwith.something').__enter__()
+++ if 1:
++ self.assertEqual(something, mock_something, "unpatched")
++ self.assertTrue(is_instance(mock_something, MagicMock),
++ "patching wrong type")
+++ mock_something.__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something)
++
++
++@@ -47,27 +53,33 @@ class WithTest(unittest2.TestCase):
++ class Foo(object):
++ something = 'foo'
++ original = Foo.something
++- with patch.object(Foo, 'something'):
+++ patch.object(Foo, 'something').__enter__()
+++ if 1:
++ self.assertNotEqual(Foo.something, original, "unpatched")
+++ patch.object(Foo, 'something').__exit__(0, 0, 0)
++ self.assertEqual(Foo.something, original)
++
++
++ def test_with_statement_nested(self):
++- with catch_warnings(record=True):
+++ catch_warnings(record=True).__enter__()
+++ if 1:
++ # nested is deprecated in Python 2.7
++ with nested(patch('tests._testwith.something'),
++ patch('tests._testwith.something_else')) as (mock_something, mock_something_else):
++ self.assertEqual(something, mock_something, "unpatched")
++ self.assertEqual(something_else, mock_something_else,
++ "unpatched")
+++ catch_warnings(record=True).__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something)
++ self.assertEqual(something_else, sentinel.SomethingElse)
++
++
++ def test_with_statement_specified(self):
++- with patch('tests._testwith.something', sentinel.Patched) as mock_something:
+++ mock_something = patch('tests._testwith.something', sentinel.Patched).__enter__()
+++ if 1:
++ self.assertEqual(something, mock_something, "unpatched")
++ self.assertEqual(mock_something, sentinel.Patched, "wrong patch")
+++ mock_something.__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something)
++
++
++@@ -77,8 +89,10 @@ class WithTest(unittest2.TestCase):
++ mock.__exit__ = Mock()
++ mock.__exit__.return_value = False
++
++- with mock as m:
+++ m = mock.__enter__()
+++ if 1:
++ self.assertEqual(m, mock.__enter__.return_value)
+++ m.__exit__(0, 0, 0)
++ mock.__enter__.assert_called_with()
++ mock.__exit__.assert_called_with(None, None, None)
++
++@@ -86,49 +100,63 @@ class WithTest(unittest2.TestCase):
++ def test_context_manager_with_magic_mock(self):
++ mock = MagicMock()
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ with mock:
++ 'foo' + 3
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ mock.__enter__.assert_called_with()
++ self.assertTrue(mock.__exit__.called)
++
++
++ def test_with_statement_same_attribute(self):
++- with patch('tests._testwith.something', sentinel.Patched) as mock_something:
+++ mock_something = patch('tests._testwith.something', sentinel.Patched).__enter__()
+++ if 1:
++ self.assertEqual(something, mock_something, "unpatched")
++
++- with patch('tests._testwith.something') as mock_again:
+++ mock_again = patch('tests._testwith.something').__enter__()
+++ if 1:
++ self.assertEqual(something, mock_again, "unpatched")
++
+++ mock_again.__exit__(0, 0, 0)
++ self.assertEqual(something, mock_something,
++ "restored with wrong instance")
++
+++ mock_something.__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something, "not restored")
++
++
++ def test_with_statement_imbricated(self):
++- with patch('tests._testwith.something') as mock_something:
+++ mock_something = patch('tests._testwith.something').__enter__()
+++ if 1:
++ self.assertEqual(something, mock_something, "unpatched")
++
++- with patch('tests._testwith.something_else') as mock_something_else:
+++ mock_something_else = patch('tests._testwith.something_else').__enter__()
+++ if 1:
++ self.assertEqual(something_else, mock_something_else,
++ "unpatched")
++
+++ mock_something_else.__exit__(0, 0, 0)
+++ mock_something.__exit__(0, 0, 0)
++ self.assertEqual(something, sentinel.Something)
++ self.assertEqual(something_else, sentinel.SomethingElse)
++
++
++ def test_dict_context_manager(self):
++ foo = {}
++- with patch.dict(foo, {'a': 'b'}):
+++ patch.dict(foo, {'a': 'b'}).__enter__()
+++ if 1:
++ self.assertEqual(foo, {'a': 'b'})
+++ patch.dict(foo, {'a': 'b'}).__exit__(0, 0, 0)
++ self.assertEqual(foo, {})
++
++- with self.assertRaises(NameError):
+++ self.assertRaises(NameError).__enter__()
+++ if 1:
++ with patch.dict(foo, {'a': 'b'}):
++ self.assertEqual(foo, {'a': 'b'})
++ raise NameError('Konrad')
++
+++ self.assertRaises(NameError).__exit__(0, 0, 0)
++ self.assertEqual(foo, {})
++
++
++@@ -137,20 +165,26 @@ class TestMockOpen(unittest2.TestCase):
++
++ def test_mock_open(self):
++ mock = mock_open()
++- with patch('%s.open' % __name__, mock, create=True) as patched:
+++ patched = patch('%s.open' % __name__, mock, create=True).__enter__()
+++ if 1:
++ self.assertIs(patched, mock)
++ open('foo')
++
+++ patched.__exit__(0, 0, 0)
++ mock.assert_called_once_with('foo')
++
++
++ def test_mock_open_context_manager(self):
++ mock = mock_open()
++ handle = mock.return_value
++- with patch('%s.open' % __name__, mock, create=True):
++- with open('foo') as f:
+++ patch('%s.open' % __name__, mock, create=True).__enter__()
+++ if 1:
+++ f = open('foo')
+++ if 1:
++ f.read()
++
+++ f.close()
+++ patch('%s.open' % __name__, mock, create=True).__exit__(0, 0, 0)
++ expected_calls = [call('foo'), call().__enter__(), call().read(),
++ call().__exit__(None, None, None)]
++ self.assertEqual(mock.mock_calls, expected_calls)
++@@ -161,19 +195,23 @@ class TestMockOpen(unittest2.TestCase):
++ mock = MagicMock()
++ mock_open(mock)
++
++- with patch('%s.open' % __name__, mock, create=True) as patched:
+++ patched = patch('%s.open' % __name__, mock, create=True).__enter__()
+++ if 1:
++ self.assertIs(patched, mock)
++ open('foo')
++
+++ patched.__exit__(0, 0, 0)
++ mock.assert_called_once_with('foo')
++
++
++ def test_read_data(self):
++ mock = mock_open(read_data='foo')
++- with patch('%s.open' % __name__, mock, create=True):
+++ patch('%s.open' % __name__, mock, create=True).__enter__()
+++ if 1:
++ h = open('bar')
++ result = h.read()
++
+++ patch('%s.open' % __name__, mock, create=True).__exit__(0, 0, 0)
++ self.assertEqual(result, 'foo')
++
++
++diff -up comm-esr31/mozilla/python/mozboot/mozboot/base.py.python3 comm-esr31/mozilla/python/mozboot/mozboot/base.py
++--- comm-esr31/mozilla/python/mozboot/mozboot/base.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozboot/mozboot/base.py 2014-10-24 11:41:35.484880121 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import re
++diff -up comm-esr31/mozilla/python/mozboot/mozboot/mach_commands.py.python3 comm-esr31/mozilla/python/mozboot/mozboot/mach_commands.py
++--- comm-esr31/mozilla/python/mozboot/mozboot/mach_commands.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozboot/mozboot/mach_commands.py 2014-10-24 11:41:35.484880121 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this,
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from mach.decorators import (
++ CommandArgument,
++diff -up comm-esr31/mozilla/python/mozboot/mozboot/osx.py.python3 comm-esr31/mozilla/python/mozboot/mozboot/osx.py
++--- comm-esr31/mozilla/python/mozboot/mozboot/osx.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozboot/mozboot/osx.py 2014-10-24 11:41:35.484880121 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import re
++@@ -197,7 +201,7 @@ class OSXBootstrapper(BaseBootstrapper):
++ try:
++ output = self.check_output([select, '--print-path'],
++ stderr=subprocess.STDOUT)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ # This seems to appear on fresh OS X machines before any Xcode
++ # has been installed. It may only occur on OS X 10.9 and later.
++ if 'unable to get active developer directory' in e.output:
++@@ -218,13 +222,13 @@ class OSXBootstrapper(BaseBootstrapper):
++ try:
++ output = self.check_output(['/usr/bin/xcrun', 'clang'],
++ stderr=subprocess.STDOUT)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ if 'license' in e.output:
++ xcodebuild = self.which('xcodebuild')
++ try:
++ subprocess.check_call([xcodebuild, '-license'],
++ stderr=subprocess.STDOUT)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ if 'requires admin privileges' in e.output:
++ self.run_as_root([xcodebuild, '-license'])
++
++@@ -372,12 +376,14 @@ class OSXBootstrapper(BaseBootstrapper):
++ def install_homebrew(self):
++ print(PACKAGE_MANAGER_INSTALL % ('Homebrew', 'Homebrew', 'Homebrew', 'brew'))
++ bootstrap = urlopen(url=HOMEBREW_BOOTSTRAP, timeout=20).read()
++- with tempfile.NamedTemporaryFile() as tf:
+++ tf = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ tf.write(bootstrap)
++ tf.flush()
++
++ subprocess.check_call(['ruby', tf.name])
++
+++ tf.__exit__(0, 0, 0)
++ def install_macports(self):
++ url = MACPORTS_URL.get(self.minor_version, None)
++ if not url:
++@@ -386,12 +392,14 @@ class OSXBootstrapper(BaseBootstrapper):
++
++ print(PACKAGE_MANAGER_INSTALL % ('MacPorts', 'MacPorts', 'MacPorts', 'port'))
++ pkg = urlopen(url=url, timeout=300).read()
++- with tempfile.NamedTemporaryFile(suffix='.pkg') as tf:
+++ tf = tempfile.NamedTemporaryFile(suffix='.pkg').__enter__()
+++ if 1:
++ tf.write(pkg)
++ tf.flush()
++
++ self.run_as_root(['installer', '-pkg', tf.name, '-target', '/'])
++
+++ tf.__exit__(0, 0, 0)
++ def _update_package_manager(self):
++ if self.package_manager == 'homebrew':
++ subprocess.check_call([self.brew, '-v', 'update'])
++@@ -406,7 +414,7 @@ class OSXBootstrapper(BaseBootstrapper):
++ try:
++ subprocess.check_output([self.brew, '-v', 'upgrade', package],
++ stderr=subprocess.STDOUT)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ if 'already installed' not in e.output:
++ raise
++ else:
++diff -up comm-esr31/mozilla/python/mozbuild/dumbmake/dumbmake.py.python3 comm-esr31/mozilla/python/mozbuild/dumbmake/dumbmake.py
++--- comm-esr31/mozilla/python/mozbuild/dumbmake/dumbmake.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/dumbmake/dumbmake.py 2014-10-24 11:41:35.484880121 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from collections import OrderedDict
++ from itertools import groupby
++diff -up comm-esr31/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py.python3 comm-esr31/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py
++--- comm-esr31/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py 2014-10-24 11:41:35.484880121 -0600
++@@ -1,7 +1,7 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++-from __future__ import unicode_literals
+++
++
++ import unittest
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/action/buildlist.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/action/buildlist.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/action/buildlist.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/action/buildlist.py 2014-10-24 11:41:35.485880117 -0600
++@@ -7,7 +7,11 @@ if the entry does not already exist.
++
++ Usage: buildlist.py <filename> <entry> [<entry> ...]
++ '''
++-from __future__ import print_function
+++def print24(msg, file=None, end="\n"):
+++ if file:
+++ file.write(msg + end)
+++ else:
+++ sys.stdout.write(msg + end)
++
++ import sys
++ import os
++@@ -29,15 +33,17 @@ def addEntriesToListFile(listFile, entri
++ for e in entries:
++ if e not in existing:
++ existing.add(e)
++- with open(listFile, 'w') as f:
+++ f = open(listFile, 'w')
+++ if 1:
++ f.write("\n".join(sorted(existing))+"\n")
+++ f.close()
++ finally:
++ lock = None
++
++
++ def main(args):
++ if len(args) < 2:
++- print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
+++ print24("Usage: buildlist.py <list file> <entry> [<entry> ...]",
++ file=sys.stderr)
++ return 1
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/action/cl.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/action/cl.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/action/cl.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/action/cl.py 2014-10-24 11:41:35.485880117 -0600
++@@ -110,9 +110,11 @@ def InvokeClWithDependencyGeneration(cmd
++ # cost of masking failure to create the directory. We'll just
++ # die on the next line though, so it's not that much of a loss.
++
++- with open(depstarget, "w") as f:
+++ f = open(depstarget, "w")
+++ if 1:
++ mk.dump(f)
++
+++ f.close()
++ return 0
++
++ def main(args):
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/action/link_deps.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/action/link_deps.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/action/link_deps.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/action/link_deps.py 2014-10-24 11:41:35.485880117 -0600
++@@ -1,3 +1,57 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++@@ -68,7 +122,7 @@ build/binaries.
++ import argparse
++ import os
++ import sys
++-from collections import OrderedDict
+++from mycollections import OrderedDict
++ from mozbuild.makeutil import (
++ Makefile,
++ read_dep_makefile,
++@@ -140,7 +194,14 @@ class DependencyLinker(Makefile):
++ if self._group == Grouping.BY_DEPFILE:
++ if depfile not in rules:
++ rules[depfile] = self.create_rule([depfile])
++- rules[depfile].add_dependencies(d if d not in self._targets else self._targets[d][0] for d in deps)
+++ my_deps = []
+++ for d in deps:
+++ if d not in self._targets:
+++ my_deps.append(d)
+++ else:
+++ my_deps.append(self._targets[d][0])
+++ rules[depfile].add_dependencies(my_deps)
+++ #rules[depfile].add_dependencies(dd not in self._targets = (self._targets[d][0] for d in deps), )[]
++ elif self._group == Grouping.ALL_TARGETS:
++ if 'all' not in rules:
++ rules['all'] = self.create_rule()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py 2014-10-24 11:41:35.485880117 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import argparse
++ import sys
++@@ -10,8 +14,8 @@ from mozpack.copier import FileCopier
++ from mozpack.manifests import InstallManifest
++
++
++-COMPLETE = 'From {dest}: Kept {existing} existing; Added/updated {updated}; ' \
++- 'Removed {rm_files} files and {rm_dirs} directories.'
+++COMPLETE = 'From %(dest)s: Kept %(existing)s existing; Added/updated %(updated)s; ' \
+++ 'Removed %(rm_files)s files and %(rm_dirs)s directories.'
++
++
++ def process_manifest(destdir, paths,
++@@ -49,12 +53,19 @@ def main(argv):
++ remove_unaccounted=not args.no_remove,
++ remove_all_directory_symlinks=not args.no_remove_all_directory_symlinks,
++ remove_empty_directories=not args.no_remove_empty_directories)
++-
++- print(COMPLETE.format(dest=args.destdir,
+++ parms = dict()
+++ parms = {"dest":args.destdir,
+++ "existing" : result.existing_files_count,
+++ "updated" : result.updated_files_count,
+++ "rm_files" : result.removed_files_count,
+++ "rm_dirs" : result.removed_directories_count}
+++
+++ #print(COMPLETE % parms)
+++ '''(dest=args.destdir,
++ existing=result.existing_files_count,
++ updated=result.updated_files_count,
++ rm_files=result.removed_files_count,
++ rm_dirs=result.removed_directories_count))
++-
+++ '''
++ if __name__ == '__main__':
++ main(sys.argv[1:])
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py 2014-10-24 11:41:35.485880117 -0600
++@@ -11,7 +11,7 @@ import argparse
++ import os
++ import sys
++
++-from io import BytesIO
+++from StringIO import StringIO as BytesIO
++
++ from buildconfig import topsrcdir
++ from header import print_header
++@@ -52,19 +52,23 @@ def process(input_dir, inc_paths, cache_
++
++ rule.add_dependencies(idl.deps)
++
++- with FileAvoidWrite(header_path) as fh:
+++ fh = FileAvoidWrite(header_path).__enter__()
+++ if 1:
++ print_header(idl, fh, path)
++
+++ fh.__exit__(0, 0, 0)
++ # TODO use FileAvoidWrite once it supports binary mode.
++ xpt_path = os.path.join(xpt_dir, '%s.xpt' % module)
++ xpt_link(xpts.values()).write(xpt_path)
++
++ rule.add_targets([xpt_path])
++ deps_path = os.path.join(deps_dir, '%s.pp' % module)
++- with FileAvoidWrite(deps_path) as fh:
+++ fh = FileAvoidWrite(deps_path).__enter__()
+++ if 1:
++ mk.dump(fh)
++
++
+++ fh.__exit__(0, 0, 0)
++ def main(argv):
++ parser = argparse.ArgumentParser()
++ parser.add_argument('--cache-dir',
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py 2014-10-24 11:41:35.486880112 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import itertools
++ import os
++@@ -16,7 +16,7 @@ from mozpack.files import (FileFinder, P
++ from mozpack.manifests import InstallManifest
++ import mozpack.path as mozpath
++
++-from .common import CommonBackend
+++from common import CommonBackend
++ from ..frontend.data import (
++ AndroidEclipseProjectData,
++ SandboxDerived,
++@@ -228,7 +228,7 @@ class AndroidEclipseBackend(CommonBacken
++ defines['IDE_CLASSPATH_ENTRIES'] = '\n'.join('\t' + cpe for cpe in classpathentries)
++ defines['IDE_RECURSIVE_MAKE_TARGETS'] = ' '.join(sorted(data.recursive_make_targets))
++ # Like android.library=true
++- defines['IDE_PROJECT_LIBRARY_SETTING'] = 'android.library=true' if data.is_library else ''
+++ defines['IDE_PROJECT_LIBRARY_SETTING'] = ('', 'android.library=true')[data.is_library]
++ # Like android.library.reference.1=FennecBrandingResources
++ defines['IDE_PROJECT_LIBRARY_REFERENCES'] = '\n'.join(
++ 'android.library.reference.%s=%s' % (i + 1, ref)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/base.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/base.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/base.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/base.py 2014-10-24 11:41:35.486880112 -0600
++@@ -1,8 +1,62 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from abc import (
++ ABCMeta,
++@@ -13,20 +67,21 @@ import errno
++ import os
++ import time
++
++-from contextlib import contextmanager
+++
++
++ from mach.mixin.logging import LoggingMixin
++
++ import mozpack.path as mozpath
++-from ..preprocessor import Preprocessor
++-from ..pythonutil import iter_modules_in_path
++-from ..util import FileAvoidWrite
++-from ..frontend.data import (
+++from preprocessor import Preprocessor
+++from pythonutil import iter_modules_in_path
+++from util import FileAvoidWrite
+++from frontend.data import (
++ ReaderSummary,
++ SandboxDerived,
++ )
++-from .configenvironment import ConfigEnvironment
+++from configenvironment import ConfigEnvironment
++ import mozpack.path as mozpath
+++from contextdecorator import contextmanager
++
++
++ class BackendConsumeSummary(object):
++@@ -83,18 +138,18 @@ class BackendConsumeSummary(object):
++
++ @property
++ def reader_summary(self):
++- return 'Finished reading {:d} moz.build files in {:.2f}s'.format(
+++ return 'Finished reading %d moz.build files in %fs' % (
++ self.mozbuild_count,
++ self.mozbuild_execution_time)
++
++ @property
++ def emitter_summary(self):
++- return 'Processed into {:d} build config descriptors in {:.2f}s'.format(
+++ return 'Processed into %d build config descriptors in %fs' % (
++ self.object_count, self.emitter_execution_time)
++
++ @property
++ def backend_summary(self):
++- return 'Backend executed in {:.2f}s'.format(self.backend_execution_time)
+++ return 'Backend executed in %fs' % (self.backend_execution_time)
++
++ def backend_detailed_summary(self):
++ """Backend summary to be supplied by BuildBackend implementations."""
++@@ -102,9 +157,13 @@ class BackendConsumeSummary(object):
++
++ @property
++ def total_summary(self):
++- efficiency_value = self.cpu_time / self.wall_time if self.wall_time else 100
++- return 'Total wall time: {:.2f}s; CPU time: {:.2f}s; Efficiency: ' \
++- '{:.0%}; Untracked: {:.2f}s'.format(
+++ efficiency_value = None
+++ if self.wall_time:
+++ efficiency_value = self.cpu_time / self.wall_time
+++ else:
+++ efficiency_value = 100
+++ return 'Total wall time: %.2fs; CPU time: %.2fs; Efficiency: ' \
+++ '%.0f; Untracked: %.2fs' % (
++ self.wall_time, self.cpu_time, efficiency_value,
++ self.other_time)
++
++@@ -179,11 +238,13 @@ class BuildBackend(LoggingMixin):
++ base class consumes objects and calls methods (possibly) implemented by
++ child classes.
++ """
+++ #print objs
++ cpu_start = time.clock()
++ time_start = time.time()
++ backend_time = 0.0
++
++ for obj in objs:
+++ #print self, obj, obj._ack
++ self.summary.object_count += 1
++ obj_start = time.time()
++ self.consume_object(obj)
++@@ -219,12 +280,16 @@ class BuildBackend(LoggingMixin):
++ # Write out the list of backend files generated, if it changed.
++ if self.summary.deleted_count or self.summary.created_count or \
++ not os.path.exists(self._backend_output_list_file):
++- with open(self._backend_output_list_file, 'w') as fh:
+++ fh = open(self._backend_output_list_file, 'w')
+++ if 1:
++ fh.write('\n'.join(sorted(self._backend_output_files)))
+++ fh.__exit__(0, 0, 0)
++ elif self.summary.updated_count:
++- with open(self._backend_output_list_file, 'a'):
+++ open(self._backend_output_list_file, 'a').__enter__()
+++ if 1:
++ os.utime(self._backend_output_list_file, None)
++
+++ open(self._backend_output_list_file, 'a').__exit__(0, 0, 0)
++ self.summary.cpu_time = time.clock() - cpu_start
++ self.summary.wall_time = time.time() - time_start
++ self.summary.backend_execution_time = backend_time
++@@ -255,8 +320,10 @@ class BuildBackend(LoggingMixin):
++
++ Example usage:
++
++- with self._write_file('foo.txt') as fh:
+++ fh = self._write_file('foo.txt').__enter__()
+++ if 1:
++ fh.write('hello world')
+++ fh.close()
++ """
++
++ if path is not None:
++@@ -268,12 +335,13 @@ class BuildBackend(LoggingMixin):
++ dirname = mozpath.dirname(fh.name)
++ try:
++ os.makedirs(dirname)
++- except OSError as error:
+++ except OSError, error:
++ if error.errno != errno.EEXIST:
++ raise
++
+++ #print "preYIELD"
++ yield fh
++-
+++ #print "Ceka na yield?"
++ self._backend_output_files.add(mozpath.relpath(fh.name, self.environment.topobjdir))
++ existed, updated = fh.close()
++ if not existed:
++@@ -301,6 +369,9 @@ class BuildBackend(LoggingMixin):
++ )
++ pp.do_filter('attemptSubstitution')
++ pp.setMarker(None)
++- with self._write_file(obj.output_path) as fh:
+++ fh = self._write_file(obj.output_path).__enter__()
+++ if 1:
++ pp.out = fh
++ yield pp
+++ fh.__exit__(0, 0, 0)
+++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/common.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/common.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/common.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/common.py 2014-10-24 11:41:35.486880112 -0600
++@@ -1,18 +1,72 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
++
++-import json
+++
+++import simplejson as json
++ import os
++ import re
++
++ import mozpack.path as mozpath
++
++-from .base import BuildBackend
+++from base import BuildBackend
++
++-from ..frontend.data import (
+++from mozbuild.frontend.data import (
++ ConfigFileSubstitution,
++ ExampleWebIDLInterface,
++ HeaderFileSubstitution,
++@@ -26,7 +80,7 @@ from ..frontend.data import (
++ WebIDLFile,
++ )
++
++-from ..util import DefaultOnReadDict
+++from util import DefaultOnReadDict
++
++
++ class XPIDLManager(object):
++@@ -188,8 +242,10 @@ class CommonBackend(BuildBackend):
++ # to other
++ if mozpath.basename(obj.output_path) == 'Makefile':
++ return
++- with self._get_preprocessor(obj) as pp:
+++ pp = self._get_preprocessor(obj).__enter__()
+++ if 1:
++ pp.do_include(obj.input_path)
+++ pp.out.close() #__exit__(0, 0, 0)
++ self.backend_input_files.add(obj.input_path)
++
++ elif isinstance(obj, HeaderFileSubstitution):
++@@ -239,10 +295,13 @@ class CommonBackend(BuildBackend):
++
++ # Write out a machine-readable file describing every test.
++ path = mozpath.join(self.environment.topobjdir, 'all-tests.json')
++- with self._write_file(path) as fh:
+++ fh = file(path, "w")
+++ #fh = self._write_file(path)
+++ if 1:
++ json.dump(self._test_manager.tests_by_path, fh, sort_keys=True,
++ indent=2)
++
+++ fh.close()
++ def _create_config_header(self, obj):
++ '''Creates the given config header. A config header is generated by
++ taking the corresponding source file and replacing some #define/#undef
++@@ -253,8 +312,11 @@ class CommonBackend(BuildBackend):
++ "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
++ Whitespaces are preserved.
++ '''
++- with self._write_file(obj.output_path) as fh, \
++- open(obj.input_path, 'rU') as input:
+++ fh = self._write_file(obj.output_path).__enter__()
+++ input = open(obj.input_path, 'rU')
+++ if 1:
+++ #with self._write_file(obj.output_path) as fh, \
+++ # open(obj.input_path, 'rU') as input:
++ r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
++ for l in input:
++ m = r.match(l)
++@@ -277,5 +339,7 @@ class CommonBackend(BuildBackend):
++ + l[m.end('name'):]
++ elif cmd == 'undef':
++ l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
++-
+++ #print dir(fh)
++ fh.write(l)
+++ fh.close() #__exit__(None, None, None)
+++ input.close()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py 2014-10-24 11:41:35.486880112 -0600
++@@ -4,21 +4,22 @@
++
++ import sys
++
++-from collections import Iterable
+++from rhrebase import isIterable
+++#from collections import Iterable
++ from types import StringTypes
++
++ import mozpack.path as mozpath
++
++-from ..util import (
+++from util import (
++ ReadOnlyDict,
++ shell_quote,
++ )
++
++
++-if sys.version_info.major == 2:
++- text_type = unicode
++-else:
++- text_type = str
+++#if sys.version_info.major == 2:
+++text_type = str
+++#else:
+++text_type = str
++
++
++ class BuildConfig(object):
++@@ -36,9 +37,10 @@ class BuildConfig(object):
++ def from_config_status(path):
++ """Create an instance from a config.status file."""
++
++- with open(path, 'rt') as fh:
+++ fh = open(path, 'rt')
+++ if 1:
++ source = fh.read()
++- code = compile(source, path, 'exec', dont_inherit=1)
+++ code = compile(source, path, 'exec', 0, 1)
++ g = {
++ '__builtins__': __builtins__,
++ '__file__': path,
++@@ -51,7 +53,8 @@ class BuildConfig(object):
++ for name in l['__all__']:
++ setattr(config, name, l[name])
++
++- return config
+++ fh.close()
+++ return config
++
++
++ class ConfigEnvironment(object):
++@@ -115,7 +118,7 @@ class ConfigEnvironment(object):
++ def serialize(obj):
++ if isinstance(obj, StringTypes):
++ return obj
++- if isinstance(obj, Iterable):
+++ if isIterable(obj):
++ return ' '.join(obj)
++ raise Exception('Unhandled type %s', type(obj))
++ self.substs['ALLSUBSTS'] = '\n'.join(sorted(['%s = %s' % (name,
++@@ -143,7 +146,7 @@ class ConfigEnvironment(object):
++
++ for k, v in self.substs.items():
++ if not isinstance(v, StringTypes):
++- if isinstance(v, Iterable):
+++ if isIterable(v):
++ type(v)(decode(i) for i in v)
++ elif not isinstance(v, text_type):
++ v = decode(v)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py 2014-10-24 11:41:35.487880108 -0600
++@@ -7,7 +7,7 @@ import errno
++ import types
++ import os
++ import xml.etree.ElementTree as ET
++-from .common import CommonBackend
+++from common import CommonBackend
++
++ from ..frontend.data import (
++ Defines,
++@@ -67,40 +67,52 @@ class CppEclipseBackend(CommonBackend):
++ for dir_name in [self._project_dir, settings_dir, launch_dir, workspace_settings_dir, workspace_language_dir]:
++ try:
++ os.makedirs(dir_name)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++
++ project_path = os.path.join(self._project_dir, '.project')
++- with open(project_path, 'wb') as fh:
+++ fh = open(project_path, 'wb')
+++ if 1:
++ self._write_project(fh)
++
+++ fh.close()
++ cproject_path = os.path.join(self._project_dir, '.cproject')
++- with open(cproject_path, 'wb') as fh:
+++ fh = open(cproject_path, 'wb')
+++ if 1:
++ self._write_cproject(fh)
++
+++ fh.close()
++ language_path = os.path.join(settings_dir, 'language.settings.xml')
++- with open(language_path, 'wb') as fh:
+++ fh = open(language_path, 'wb')
+++ if 1:
++ self._write_language_settings(fh)
++
+++ fh.close()
++ workspace_language_path = os.path.join(workspace_language_dir, 'language.settings.xml')
++- with open(workspace_language_path, 'wb') as fh:
+++ fh = open(workspace_language_path, 'wb')
+++ if 1:
++ workspace_lang_settings = WORKSPACE_LANGUAGE_SETTINGS_TEMPLATE
++ workspace_lang_settings = workspace_lang_settings.replace("@COMPILER_FLAGS@", self._cxx + " " + self._cppflags);
++ fh.write(workspace_lang_settings)
++
+++ fh.close()
++ self._write_launch_files(launch_dir)
++
++ # This will show up as an 'unmanged' formatter. This can be named by generating
++ # another file.
++ formatter_prefs_path = os.path.join(settings_dir, 'org.eclipse.cdt.core.prefs')
++- with open(formatter_prefs_path, 'wb') as fh:
+++ fh = open(formatter_prefs_path, 'wb')
+++ if 1:
++ fh.write(FORMATTER_SETTINGS);
++
+++ fh.close()
++ editor_prefs_path = os.path.join(workspace_settings_dir, "org.eclipse.ui.editors.prefs");
++- with open(editor_prefs_path, 'wb') as fh:
+++ fh = open(editor_prefs_path, 'wb')
+++ if 1:
++ fh.write(EDITOR_SETTINGS);
++
+++ fh.close()
++ def _define_entry(self, name, value):
++ define = ET.Element('entry')
++ define.set('kind', 'macro')
++@@ -134,15 +146,18 @@ class CppEclipseBackend(CommonBackend):
++
++ if self.environment.substs['MOZ_WIDGET_TOOLKIT'] != 'gonk':
++ main_gecko_launch = os.path.join(launch_dir, 'gecko.launch')
++- with open(main_gecko_launch, 'wb') as fh:
+++ fh = open(main_gecko_launch, 'wb')
+++ if 1:
++ launch = GECKO_LAUNCH_CONFIG_TEMPLATE
++ launch = launch.replace('@LAUNCH_PROGRAM@', exe_path)
++ launch = launch.replace('@LAUNCH_ARGS@', '-P -no-remote')
++ fh.write(launch)
++
+++ fh.close()
++ if self.environment.substs['MOZ_WIDGET_TOOLKIT'] == 'gonk':
++ b2g_flash = os.path.join(launch_dir, 'b2g-flash.launch')
++- with open(b2g_flash, 'wb') as fh:
+++ fh = open(b2g_flash, 'wb')
+++ if 1:
++ # We assume that the srcdir is inside the b2g tree.
++ # If that's not the case the user can always adjust the path
++ # from the eclipse IDE.
++@@ -152,6 +167,7 @@ class CppEclipseBackend(CommonBackend):
++ launch = launch.replace('@OBJDIR@', self.environment.topobjdir)
++ fh.write(launch)
++
+++ fh.close()
++ #TODO Add more launch configs (and delegate calls to mach)
++
++ def _write_project(self, fh):
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py 2014-10-24 11:41:35.487880108 -0600
++@@ -1,16 +1,106 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++class ZipExhausted(Exception):
+++ pass
+++
+++def next(iter):
+++ return iter.next()
+++
+++def izip_longest(*args, **kwds):
+++ # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
+++ fillvalue = kwds.get('fillvalue')
+++ counter = [len(args) - 1]
+++ def sentinel():
+++ if not counter[0]:
+++ raise ZipExhausted
+++ counter[0] -= 1
+++ yield fillvalue
+++ fillers = repeat(fillvalue)
+++ iterators = [chain(it, sentinel(), fillers) for it in args]
+++ try:
+++ while iterators:
+++ yield tuple(map(next, iterators))
+++ except ZipExhausted:
+++ pass
+++
+++def repeat(object, times=None):
+++ # repeat(10, 3) --> 10 10 10
+++ if times is None:
+++ while True:
+++ yield object
+++ else:
+++ for i in xrange(times):
+++ yield object
+++
+++def chain(*iterables):
+++ # chain('ABC', 'DEF') --> A B C D E F
+++ for it in iterables:
+++ for element in it:
+++ yield element
++
++ import itertools
++-import json
+++import simplejson as json
++ import logging
++ import os
++ import types
++
++-from collections import namedtuple
+++from namedtuple import namedtuple
++
++ import mozwebidlcodegen
++
++@@ -21,8 +111,8 @@ from mozpack.manifests import (
++ )
++ import mozpack.path as mozpath
++
++-from .common import CommonBackend
++-from ..frontend.data import (
+++from common import CommonBackend
+++from mozbuild.frontend.data import (
++ AndroidEclipseProjectData,
++ ConfigFileSubstitution,
++ Defines,
++@@ -47,11 +137,11 @@ from ..frontend.data import (
++ VariablePassthru,
++ XPIDLFile,
++ )
++-from ..util import (
+++from util import (
++ ensureParentDir,
++ FileAvoidWrite,
++ )
++-from ..makeutil import Makefile
+++from makeutil import Makefile
++
++ class BackendMakeFile(object):
++ """Represents a generated backend.mk file.
++@@ -190,8 +280,7 @@ class RecursiveMakeTraversal(object):
++ where current is the directory being traversed, and subdirs the
++ SubDirectories instance corresponding to it.
++ The filter function returns a tuple (filtered_current, filtered_parallel,
++- filtered_dirs) where filtered_current is either current or None if
++- the current directory is to be skipped, and filtered_parallel and
+++ filtered_dirs) where filtered_current is either current or None if the current directory is to be skipped, and filtered_parallel and
++ filtered_dirs are lists of parallel directories and sequential
++ directories, which can be rearranged from whatever is given in the
++ SubDirectories members.
++@@ -272,9 +361,9 @@ class RecursiveMakeBackend(CommonBackend
++ self._ipdl_sources = set()
++
++ def detailed(summary):
++- s = '{:d} total backend files; ' \
++- '{:d} created; {:d} updated; {:d} unchanged; ' \
++- '{:d} deleted; {:d} -> {:d} Makefile'.format(
+++ s = '%d total backend files; ' \
+++ '%d created; %d updated; %d unchanged; ' \
+++ '%d deleted; %d -> %d Makefile' % (
++ summary.created_count + summary.updated_count +
++ summary.unchanged_count,
++ summary.created_count,
++@@ -297,6 +386,18 @@ class RecursiveMakeBackend(CommonBackend
++ self.backend_input_files.add(mozpath.join(self.environment.topobjdir,
++ 'config', 'autoconf.mk'))
++
+++ self._install_manifests = {}
+++ for k in [
+++ 'dist_bin',
+++ 'dist_idl',
+++ 'dist_include',
+++ 'dist_public',
+++ 'dist_private',
+++ 'dist_sdk',
+++ 'tests',
+++ 'xpidl']:
+++ self._install_manifests[k] = InstallManifest()
+++ '''
++ self._install_manifests = {
++ k: InstallManifest() for k in [
++ 'dist_bin',
++@@ -308,7 +409,7 @@ class RecursiveMakeBackend(CommonBackend
++ 'tests',
++ 'xpidl',
++ ]}
++-
+++ '''
++ self._traversal = RecursiveMakeTraversal()
++ self._may_skip = {
++ 'export': set(),
++@@ -330,7 +431,7 @@ class RecursiveMakeBackend(CommonBackend
++
++ if not isinstance(obj, SandboxDerived):
++ return
++-
+++ #print "consume obj", obj
++ if obj.objdir not in self._backend_files:
++ self._backend_files[obj.objdir] = \
++ BackendMakeFile(obj.srcdir, obj.objdir, obj.config)
++@@ -348,8 +449,10 @@ class RecursiveMakeBackend(CommonBackend
++ self._process_test_manifest(obj, backend_file)
++
++ # If CommonBackend acknowledged the object, we're done with it.
+++ #print "pre ack", obj
++ if obj._ack:
++ return
+++ #print "post ack", obj
++
++ if isinstance(obj, DirectoryTraversal):
++ self._process_directory_traversal(obj, backend_file)
++@@ -466,7 +569,9 @@ class RecursiveMakeBackend(CommonBackend
++ self._process_library_definition(obj, backend_file)
++
++ else:
+++ #print "wasn't ack", obj
++ return
+++ #print "acking"
++ obj.ack()
++
++ def _fill_root_mk(self):
++@@ -479,7 +584,7 @@ class RecursiveMakeBackend(CommonBackend
++ for tier, skip in self._may_skip.items():
++ self.log(logging.DEBUG, 'fill_root_mk', {
++ 'number': len(skip), 'tier': tier
++- }, 'Ignoring {number} directories during {tier}')
+++ }, 'Ignoring %(number)d directories during %(tier)s')
++
++ # Traverse directories in parallel, and skip static dirs
++ def parallel_filter(current, subdirs):
++@@ -589,14 +694,16 @@ class RecursiveMakeBackend(CommonBackend
++
++ root_mk.add_statement('$(call include_deps,root-deps.mk)')
++
++- with self._write_file(
++- mozpath.join(self.environment.topobjdir, 'root.mk')) as root:
+++ root = self._write_file( mozpath.join(self.environment.topobjdir, 'root.mk')).__enter__()
+++ if 1:
++ root_mk.dump(root, removal_guard=False)
++
++- with self._write_file(
++- mozpath.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
+++ root.__exit__(0, 0, 0)
+++ root_deps = self._write_file( mozpath.join(self.environment.topobjdir, 'root-deps.mk')).__enter__()
+++ if 1:
++ root_deps_mk.dump(root_deps, removal_guard=False)
++
+++ root_deps.__exit__(0, 0, 0)
++ def _add_unified_build_rules(self, makefile, files, output_directory,
++ unified_prefix='Unified',
++ unified_suffix='cpp',
++@@ -631,14 +738,17 @@ class RecursiveMakeBackend(CommonBackend
++ def grouper(n, iterable):
++ "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
++ args = [iter(iterable)] * n
++- return itertools.izip_longest(fillvalue=dummy_fill_value, *args)
+++ #return itertools.izip_longest(fillvalue=dummy_fill_value, *args)
+++ #return itertools.izip(fillvalue=dummy_fill_value, *args)
+++ return izip_longest(fillvalue=dummy_fill_value, *args)
++
++ for i, unified_group in enumerate(grouper(files_per_unified_file,
++ files)):
++ just_the_filenames = list(filter_out_dummy(unified_group))
++ yield '%s%d.%s' % (unified_prefix, i, unified_suffix), just_the_filenames
++
++- all_sources = ' '.join(source for source, _ in unified_files())
+++ my_unified_files = [f for f in unified_files()]
+++ all_sources = ' '.join(source for source, _ in my_unified_files)
++ makefile.add_statement('%s := %s' % (unified_files_makefile_variable,
++ all_sources))
++
++@@ -651,7 +761,8 @@ class RecursiveMakeBackend(CommonBackend
++ # blown away and we need to regenerate them. The rule doesn't correctly
++ # handle source files being added/removed/renamed. Therefore, we
++ # generate them here also to make sure everything's up-to-date.
++- with self._write_file(mozpath.join(output_directory, unified_file)) as f:
+++ f = self._write_file(mozpath.join(output_directory, unified_file)).__enter__()
+++ if 1:
++ f.write('#define MOZ_UNIFIED_BUILD\n')
++ includeTemplate = '#include "%(cppfile)s"'
++ if poison_windows_h:
++@@ -680,6 +791,7 @@ class RecursiveMakeBackend(CommonBackend
++ f.write('\n'.join(includeTemplate % { "cppfile": s } for
++ s in source_filenames))
++
+++ f.close() #f.__exit__(0, 0, 0)
++ if include_curdir_build_rules:
++ makefile.add_statement('\n'
++ '# Make sometimes gets confused between "foo" and "$(CURDIR)/foo".\n'
++@@ -695,7 +807,8 @@ class RecursiveMakeBackend(CommonBackend
++
++ for objdir, backend_file in sorted(self._backend_files.items()):
++ srcdir = backend_file.srcdir
++- with self._write_file(fh=backend_file) as bf:
+++ bf = self._write_file(fh=backend_file).__enter__()
+++ if 1:
++ makefile_in = mozpath.join(srcdir, 'Makefile.in')
++ makefile = mozpath.join(objdir, 'Makefile')
++
++@@ -724,6 +837,7 @@ class RecursiveMakeBackend(CommonBackend
++ obj.config = bf.environment
++ self._create_makefile(obj, stub=stub)
++
+++ bf.close()
++ # Write out a master list of all IPDL source files.
++ ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
++ mk = mozmakeutil.Makefile()
++@@ -751,15 +865,27 @@ class RecursiveMakeBackend(CommonBackend
++ mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(mozpath.dirname(p)
++ for p in self._ipdl_sources))))
++
++- with self._write_file(mozpath.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls:
+++ ipdls = self._write_file(mozpath.join(ipdl_dir, 'ipdlsrcs.mk')).__enter__()
+++ #ipdls = file(mozpath.join(ipdl_dir, 'ipdlsrcs.mk'), "w")
+++ if 1:
++ mk.dump(ipdls, removal_guard=False)
++
+++ ipdls.__exit__(0,0,0)
++ # These contain autogenerated sources that the build config doesn't
++ # yet know about.
++ # TODO Emit GENERATED_SOURCES so these special cases are dealt with
++ # the proper way.
++- self._may_skip['compile'] -= {'ipc/ipdl'}
++- self._may_skip['compile'] -= {'dom/bindings', 'dom/bindings/test'}
+++ #print self._may_skip['compile']
+++ if 'ipc/ipdl' in self._may_skip['compile']:
+++ self._may_skip['compile'].remove('ipc/ipdl')
+++ #print self._may_skip['compile']
+++ #self._may_skip['compile'] -= {'ipc/ipdl'}
+++ if 'dom/bindings' in self._may_skip['compile']:
+++ self._may_skip['compile'].remove('dom/bindings')
+++ if 'dom/bindings/test' in self._may_skip['compile']:
+++ self._may_skip['compile'].remove('dom/bindings/test')
+++ #print self._may_skip['compile']
+++ #self._may_skip['compile'] -= {'dom/bindings', 'dom/bindings/test'}
++
++ self._fill_root_mk()
++
++@@ -770,13 +896,16 @@ class RecursiveMakeBackend(CommonBackend
++ # We need to use $(DEPTH) so the target here matches what's in
++ # rules.mk. If they are different, the dependencies don't get pulled in
++ # properly.
++- with self._write_file('%s.pp' % self._backend_output_list_file) as backend_deps:
+++ backend_deps = self._write_file('%s.pp' % self._backend_output_list_file).__enter__()
+++ if 1:
++ backend_deps.write('$(DEPTH)/backend.%s: %s\n' %
++ (self.__class__.__name__, ' '.join(inputs)))
++ for path in inputs:
++ backend_deps.write('%s:\n' % path)
++
++- with open(self._backend_output_list_file, 'a'):
+++ backend_deps.__exit__(0, 0, 0)
+++ open(self._backend_output_list_file, 'a')
+++ if 1:
++ pass
++ os.utime(self._backend_output_list_file, None)
++
++@@ -1047,8 +1176,7 @@ class RecursiveMakeBackend(CommonBackend
++ obj.manifest_relpath))
++
++ # Don't allow files to be defined multiple times unless it is allowed.
++- # We currently allow duplicates for non-test files or test files if
++- # the manifest is listed as a duplicate.
+++ # We currently allow duplicates for non-test files or test files if # the manifest is listed as a duplicate.
++ for source, (dest, is_test) in obj.installs.items():
++ try:
++ self._install_manifests['tests'].add_symlink(source, dest)
++@@ -1154,22 +1282,28 @@ class RecursiveMakeBackend(CommonBackend
++ # manifests are deleted.
++ purger = FilePurger()
++
+++ #print(manifests.items())
++ for k, manifest in manifests.items():
++ purger.add(k)
+++ fh = self._write_file(mozpath.join(man_dir, k)).__enter__()
+++ if 1:
+++ manifest.write(fileobj=fh)
+++ fh.close()
++
++- with self._write_file(mozpath.join(man_dir, k)) as fh:
++- manifest.write(fileobj=fh)
+++ #with self._write_file(mozpath.join(man_dir, k)) as fh:
+++ # manifest.write(fileobj=fh)
++
++ purger.purge(man_dir)
++
++ def _write_master_test_manifest(self, path, manifests):
++- with self._write_file(path) as master:
+++ master = self._write_file(path).__enter__()
+++ if 1:
++ master.write(
++ '; THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n\n')
++
++ for manifest in sorted(manifests):
++ master.write('[include:%s]\n' % manifest)
++-
+++ master.__exit__(0, 0, 0)
++ class Substitution(object):
++ """BaseConfigSubstitution-like class for use with _create_makefile."""
++ __slots__ = (
++@@ -1188,24 +1322,26 @@ class RecursiveMakeBackend(CommonBackend
++ When the stub argument is True, no source file is used, and a stub
++ makefile with the default header and footer only is created.
++ '''
++- with self._get_preprocessor(obj) as pp:
+++ pp = self._get_preprocessor(obj).__enter__()
+++ if 1:
++ if extra:
++ pp.context.update(extra)
++ if not pp.context.get('autoconfmk', ''):
++ pp.context['autoconfmk'] = 'autoconf.mk'
++- pp.handleLine(b'# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
++- pp.handleLine(b'DEPTH := @DEPTH@\n')
++- pp.handleLine(b'topsrcdir := @top_srcdir@\n')
++- pp.handleLine(b'srcdir := @srcdir@\n')
++- pp.handleLine(b'VPATH := @srcdir@\n')
++- pp.handleLine(b'relativesrcdir := @relativesrcdir@\n')
++- pp.handleLine(b'include $(DEPTH)/config/@autoconfmk@\n')
+++ pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
+++ pp.handleLine('DEPTH := @DEPTH@\n')
+++ pp.handleLine('topsrcdir := @top_srcdir@\n')
+++ pp.handleLine('srcdir := @srcdir@\n')
+++ pp.handleLine('VPATH := @srcdir@\n')
+++ pp.handleLine('relativesrcdir := @relativesrcdir@\n')
+++ pp.handleLine('include $(DEPTH)/config/@autoconfmk@\n')
++ if not stub:
++ pp.do_include(obj.input_path)
++ # Empty line to avoid failures when last line in Makefile.in ends
++ # with a backslash.
++- pp.handleLine(b'\n')
++- pp.handleLine(b'include $(topsrcdir)/config/recurse.mk\n')
+++ pp.handleLine('\n')
+++ pp.handleLine('include $(topsrcdir)/config/recurse.mk\n')
+++ pp.out.close()
++ if not stub:
++ # Adding the Makefile.in here has the desired side-effect
++ # that if the Makefile.in disappears, this will force
++@@ -1240,9 +1376,11 @@ class RecursiveMakeBackend(CommonBackend
++ )
++
++ file_lists = mozpath.join(bindings_dir, 'file-lists.json')
++- with self._write_file(file_lists) as fh:
+++ fh = self._write_file(file_lists).__enter__()
+++ if 1:
++ json.dump(o, fh, sort_keys=True, indent=2)
++
+++ fh.close() #__exit__(0, 0, 0)
++ manager = mozwebidlcodegen.create_build_system_manager(
++ self.environment.topsrcdir,
++ self.environment.topobjdir,
++@@ -1297,5 +1435,8 @@ class RecursiveMakeBackend(CommonBackend
++ poison_windows_h=True)
++
++ webidls_mk = mozpath.join(bindings_dir, 'webidlsrcs.mk')
++- with self._write_file(webidls_mk) as fh:
+++ fh = self._write_file(webidls_mk).__enter__()
+++ if 1:
++ mk.dump(fh, removal_guard=False)
+++ fh.close() #exit__(0, 0, 0)
+++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py 2014-10-24 11:41:35.488880104 -0600
++@@ -5,7 +5,7 @@
++ # This file contains a build backend for generating Visual Studio project
++ # files.
++
++-from __future__ import unicode_literals
+++
++
++ import errno
++ import os
++@@ -17,7 +17,7 @@ from xml.dom import getDOMImplementation
++
++ from mozpack.files import FileFinder
++
++-from .common import CommonBackend
+++from common import CommonBackend
++ from ..frontend.data import (
++ Defines,
++ LibraryDefinition,
++@@ -122,7 +122,7 @@ class VisualStudioBackend(CommonBackend)
++ out_dir = self._out_dir
++ try:
++ os.makedirs(out_dir)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++
++@@ -218,26 +218,34 @@ class VisualStudioBackend(CommonBackend)
++
++ # Write out a shared property file with common variables.
++ props_path = os.path.join(out_dir, 'mozilla.props')
++- with open(props_path, 'wb') as fh:
+++ fh = open(props_path, 'wb')
+++ if 1:
++ self._write_props(fh)
++
+++ fh.close()
++ # Generate some wrapper scripts that allow us to invoke mach inside
++ # a MozillaBuild-like environment. We currently only use the batch
++ # script. We'd like to use the PowerShell script. However, it seems
++ # to buffer output from within Visual Studio (surely this is
++ # configurable) and the default execution policy of PowerShell doesn't
++ # allow custom scripts to be executed.
++- with open(os.path.join(out_dir, 'mach.bat'), 'wb') as fh:
+++ fh = open(os.path.join(out_dir, 'mach.bat'), 'wb')
+++ if 1:
++ self._write_mach_batch(fh)
++
++- with open(os.path.join(out_dir, 'mach.ps1'), 'wb') as fh:
+++ fh.close()
+++ fh = open(os.path.join(out_dir, 'mach.ps1'), 'wb')
+++ if 1:
++ self._write_mach_powershell(fh)
++
+++ fh.close()
++ # Write out a solution file to tie it all together.
++ solution_path = os.path.join(out_dir, 'mozilla.sln')
++- with open(solution_path, 'wb') as fh:
+++ fh = open(solution_path, 'wb')
+++ if 1:
++ self._write_solution(fh, projects)
++
+++ fh.close()
++ def _write_solution(self, fh, projects):
++ version = visual_studio_product_to_internal_version(self._version, True)
++ # This is a Visual C++ Project type.
++@@ -425,16 +433,20 @@ class VisualStudioBackend(CommonBackend)
++
++ def _write_vs_project(self, out_dir, basename, name, **kwargs):
++ root = '%s.vcxproj' % basename
++- with open(os.path.join(out_dir, root), 'wb') as fh:
+++ fh = open(os.path.join(out_dir, root), 'wb')
+++ if 1:
++ project_id, name = VisualStudioBackend.write_vs_project(fh,
++ self._version, name, **kwargs)
++
++- with open(os.path.join(out_dir, '%s.user' % root), 'w') as fh:
+++ fh.close()
+++ fh = open(os.path.join(out_dir, '%s.user' % root), 'w')
+++ if 1:
++ fh.write('<?xml version="1.0" encoding="utf-8"?>\r\n')
++ fh.write('<Project ToolsVersion="4.0" xmlns="%s">\r\n' %
++ MSBUILD_NAMESPACE)
++ fh.write('</Project>\r\n')
++
+++ fh.close()
++ return project_id
++
++ @staticmethod
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/base.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/base.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/base.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/base.py 2014-10-24 11:41:35.488880104 -0600
++@@ -2,12 +2,16 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++-import json
+++import simplejson as json
++ import logging
++ import mozpack.path
++-import multiprocessing
+++#import multiprocessing
++ import os
++ import subprocess
++ import sys
++@@ -18,14 +22,14 @@ from mach.mixin.process import ProcessEx
++
++ from mozfile.mozfile import rmtree
++
++-from .backend.configenvironment import ConfigEnvironment
++-from .controller.clobber import Clobberer
++-from .mozconfig import (
+++from backend.configenvironment import ConfigEnvironment
+++from controller.clobber import Clobberer
+++from mozconfig import (
++ MozconfigFindException,
++ MozconfigLoadException,
++ MozconfigLoader,
++ )
++-from .virtualenv import VirtualenvManager
+++from virtualenv import VirtualenvManager
++
++
++ def ancestors(path):
++@@ -327,7 +331,11 @@ class MozbuildObject(ProcessExecutionMix
++
++ leaf = None
++
++- leaf = (substs['MOZ_APP_NAME'] if what == 'app' else what) + substs['BIN_SUFFIX']
+++ leaf = None
+++ if what == 'app':
+++ leaf = (substs['MOZ_APP_NAME'])
+++ else:
+++ leaf = (what) + substs['BIN_SUFFIX']
++ path = os.path.join(stem, leaf)
++
++ if validate_exists and not os.path.exists(path):
++@@ -421,7 +429,7 @@ class MozbuildObject(ProcessExecutionMix
++ if num_jobs > 0:
++ args.append('-j%d' % num_jobs)
++ else:
++- args.append('-j%d' % multiprocessing.cpu_count())
+++ args.append('-j%d' % 1)#multiprocessing.cpu_count())
++ elif num_jobs > 0:
++ args.append('MOZ_PARALLEL_BUILD=%d' % num_jobs)
++
++@@ -449,7 +457,7 @@ class MozbuildObject(ProcessExecutionMix
++ fn = self._run_command_in_srcdir
++
++ append_env = dict(append_env or ())
++- append_env[b'MACH'] = '1'
+++ append_env['MACH'] = '1'
++
++ params = {
++ 'args': args,
++@@ -566,11 +574,11 @@ class MachCommandBase(MozbuildObject):
++ try:
++ self.mozconfig
++
++- except MozconfigFindException as e:
+++ except MozconfigFindException, e:
++ print(e.message)
++ sys.exit(1)
++
++- except MozconfigLoadException as e:
+++ except MozconfigLoadException, e:
++ print('Error loading mozconfig: ' + e.path)
++ print('')
++ print(e.message)
++@@ -625,7 +633,11 @@ class PathArgument(object):
++ self.arg = arg
++ self.topsrcdir = topsrcdir
++ self.topobjdir = topobjdir
++- self.cwd = os.getcwd() if cwd is None else cwd
+++ self.cwd = None
+++ if cwd is None:
+++ self.cwd = os.getcwd()
+++ else:
+++ self.cwd = cwd
++
++ def relpath(self):
++ """Return a path relative to the topsrcdir or topobjdir.
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/compilation/warnings.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/compilation/warnings.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/compilation/warnings.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/compilation/warnings.py 2014-10-24 11:41:35.488880104 -0600
++@@ -4,7 +4,7 @@
++
++ # This modules provides functionality for dealing with compiler warnings.
++
++-from __future__ import unicode_literals
+++
++
++ import errno
++ import json
++@@ -261,21 +261,25 @@ class WarningsDatabase(object):
++
++ def load_from_file(self, filename):
++ """Load the database from a file."""
++- with open(filename, 'rb') as fh:
+++ fh = open(filename, 'rb')
+++ if 1:
++ self.deserialize(fh)
++
+++ fh.close()
++ def save_to_file(self, filename):
++ """Save the database to a file."""
++ try:
++ # Ensure the directory exists
++ os.makedirs(os.path.dirname(filename))
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++- with open(filename, 'wb') as fh:
+++ fh = open(filename, 'wb')
+++ if 1:
++ self.serialize(fh)
++
++
+++ fh.close()
++ class WarningsCollector(object):
++ """Collects warnings from text data.
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/config_status.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/config_status.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/config_status.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/config_status.py 2014-10-24 11:41:35.488880104 -0600
++@@ -6,7 +6,9 @@
++ # drop-in replacement for autoconf 2.13's config.status, with features
++ # borrowed from autoconf > 2.5, and additional features.
++
++-from __future__ import print_function
+++import sys
+++def print24(msg, file=sys.stdout, end="\n"):
+++ file.write(msg + end)
++
++ import logging
++ import os
++@@ -140,15 +142,20 @@ def config_status(topobjdir='.', topsrcd
++ os.chdir(topobjdir)
++ os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion']))
++
++- log_level = logging.DEBUG if options.verbose else logging.INFO
+++ log_level = None
+++ if options.verbose:
+++ log_level = logging.DEBUG
+++ else:
+++ log_level = logging.INFO
++ log_manager.add_terminal_logging(level=log_level)
++ log_manager.enable_unstructured()
++
++- print('Reticulating splines...', file=sys.stderr)
+++ print24('Reticulating splines...', file=sys.stderr)
+++ #print definitions
++ summary = the_backend.consume(definitions)
++
++ for line in summary.summaries():
++- print(line, file=sys.stderr)
+++ print24(line, file=sys.stderr)
++
++ if options.diff:
++ for path, diff in sorted(summary.file_diffs.items()):
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/controller/building.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/controller/building.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/controller/building.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/controller/building.py 2014-10-24 11:41:35.489880100 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import getpass
++ import json
++@@ -258,9 +258,11 @@ class BuildMonitor(MozbuildObject):
++ if not usage:
++ return
++
++- with open(self._get_state_filename('build_resources.json'), 'w') as fh:
+++ fh = open(self._get_state_filename('build_resources.json'), 'w')
+++ if 1:
++ json.dump(usage, fh, indent=2)
++- except Exception as e:
+++ fh.close()
+++ except Exception, e:
++ self.log(logging.WARNING, 'build_resources_error',
++ {'msg': str(e)},
++ 'Exception when writing resource usage file: {msg}')
++@@ -451,7 +453,7 @@ class BuildDriver(MozbuildObject):
++
++ env = {}
++ if not remove:
++- env[b'NO_REMOVE'] = b'1'
+++ env[b'NO_REMOVE'] = '1'
++
++ self._run_make(target='install-tests', append_env=env, pass_thru=True,
++ print_directory=False)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/controller/clobber.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/controller/clobber.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/controller/clobber.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/controller/clobber.py 2014-10-24 11:41:35.489880100 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function
+++def print24(msg, file=None, end=""):
+++ if file:
+++ file.write(msg + end)
+++ else:
+++ sys.stdout.write(msg + end)
++
++ r'''This module contains code for managing clobbering of the tree.'''
++
++@@ -77,10 +81,12 @@ class Clobberer(object):
++ This returns a list of lines describing why the clobber was required.
++ Each line is stripped of leading and trailing whitespace.
++ """
++- with open(self.src_clobber, 'rt') as fh:
+++ fh = open(self.src_clobber, 'rt')
+++ if 1:
++ lines = [l.strip() for l in fh.readlines()]
++ return [l for l in lines if l and not l.startswith('#')]
++
+++ fh.close()
++ def ensure_objdir_state(self):
++ """Ensure the CLOBBER file in the objdir exists.
++
++@@ -92,7 +98,8 @@ class Clobberer(object):
++
++ if not os.path.exists(self.obj_clobber):
++ # Simply touch the file.
++- with open(self.obj_clobber, 'a'):
+++ open(self.obj_clobber, 'a')
+++ if 1:
++ pass
++
++ def maybe_do_clobber(self, cwd, allow_auto=False, fh=sys.stderr):
++@@ -113,7 +120,7 @@ class Clobberer(object):
++ cwd = os.path.normpath(cwd)
++
++ if not self.clobber_needed():
++- print('Clobber not needed.', file=fh)
+++ print24('Clobber not needed.', file=fh)
++ self.ensure_objdir_state()
++ return False, False, None
++
++@@ -134,7 +141,7 @@ class Clobberer(object):
++ return True, False, self._message(
++ 'Cannot clobber while the shell is inside the object directory.')
++
++- print('Automatically clobbering %s' % self.topobjdir, file=fh)
+++ print24('Automatically clobbering %s' % self.topobjdir, file=fh)
++ try:
++ if cwd == self.topobjdir:
++ for entry in os.listdir(self.topobjdir):
++@@ -149,9 +156,9 @@ class Clobberer(object):
++ rmtree(self.topobjdir)
++
++ self.ensure_objdir_state()
++- print('Successfully completed auto clobber.', file=fh)
+++ print24('Successfully completed auto clobber.', file=fh)
++ return True, True, None
++- except (IOError) as error:
+++ except (IOError), error:
++ return True, False, self._message(
++ 'Error when automatically clobbering: ' + str(error))
++
++@@ -164,7 +171,7 @@ class Clobberer(object):
++
++ def main(args, env, cwd, fh=sys.stderr):
++ if len(args) != 2:
++- print('Usage: clobber.py topsrcdir topobjdir', file=fh)
+++ print24('Usage: clobber.py topsrcdir topobjdir', file=fh)
++ return 1
++
++ topsrcdir, topobjdir = args
++@@ -175,16 +182,20 @@ def main(args, env, cwd, fh=sys.stderr):
++ if not os.path.isabs(topobjdir):
++ topobjdir = os.path.abspath(topobjdir)
++
++- auto = True if env.get('AUTOCLOBBER', False) else False
+++ auto = None
+++ if env.get('AUTOCLOBBER', False):
+++ auto = True
+++ else:
+++ auto = False
++ clobber = Clobberer(topsrcdir, topobjdir)
++ required, performed, message = clobber.maybe_do_clobber(cwd, auto, fh)
++
++ if not required or performed:
++ if performed and env.get('TINDERBOX_OUTPUT'):
++- print('TinderboxPrint: auto clobber', file=fh)
+++ print24('TinderboxPrint: auto clobber', file=fh)
++ return 0
++
++- print(message, file=fh)
+++ print24(message, file=fh)
++ return 1
++
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/data.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/data.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/data.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/data.py 2014-10-24 11:41:35.489880100 -0600
++@@ -15,17 +15,18 @@ contains the code for converting execute
++ structures.
++ """
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++-from collections import OrderedDict
+++from ordereddict import OrderedDict
+++
++ from mozbuild.util import (
++ shell_quote,
++ StrictOrderingOnAppendList,
++ )
++ import mozpack.path as mozpath
++-from .sandbox_symbols import FinalTargetValue
+++from sandbox_symbols import FinalTargetValue
++
++
++ class TreeMetadata(object):
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/emitter.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/emitter.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/emitter.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/emitter.py 2014-10-24 11:41:35.490880096 -0600
++@@ -1,10 +1,64 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
++
++-import json
+++
+++import simplejson as json
++ import logging
++ import os
++ import traceback
++@@ -16,7 +70,7 @@ from mach.mixin.logging import LoggingMi
++ import mozpack.path as mozpath
++ import manifestparser
++
++-from .data import (
+++from data import (
++ ConfigFileSubstitution,
++ Defines,
++ DirectoryTraversal,
++@@ -48,12 +102,12 @@ from .data import (
++ XPIDLFile,
++ )
++
++-from .reader import (
+++from reader import (
++ MozbuildSandbox,
++ SandboxValidationError,
++ )
++
++-from .gyp_reader import GypSandbox
+++from gyp_reader import GypSandbox
++
++
++ class TreeMetadataEmitter(LoggingMixin):
++@@ -93,8 +147,8 @@ class TreeMetadataEmitter(LoggingMixin):
++ def emit_objs(objs):
++ for o in objs:
++ yield o
++- if not o._ack:
++- raise Exception('Unhandled object of type %s' % type(o))
+++ #TEMP if not o._ack:
+++ # raise Exception('Unhandled object of type %s' % type(o))
++
++ for out in output:
++ if isinstance(out, (MozbuildSandbox, GypSandbox)):
++@@ -299,7 +353,12 @@ class TreeMetadataEmitter(LoggingMixin):
++
++ no_pgo = sandbox.get('NO_PGO')
++ sources = sandbox.get('SOURCES', [])
++- no_pgo_sources = [f for f in sources if sources[f].no_pgo]
+++ #print (sources)
+++ #print sources.__class__
+++ #print dir(sources)
+++ no_pgo_sources = []
+++
+++ #no_pgo_sources = [f for f in sources if sources[f].no_pgo]
++ if no_pgo:
++ if no_pgo_sources:
++ raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo cannot be set at the same time')
++@@ -307,7 +366,15 @@ class TreeMetadataEmitter(LoggingMixin):
++ if no_pgo_sources:
++ passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
++
++- sources_with_flags = [f for f in sources if sources[f].flags]
+++ sources_with_flags = []
+++ #print "NOTLIST", type(sources),
+++ #print sources, type(sources), sources.index
+++ if not type(sources) == list:
+++ for f in sources:
+++ #print f
+++ #print sources[i], type(sources[i]), sources[i].flags
+++ if sources[f].flags:
+++ sources_with_flags.append(f)
++ for f in sources_with_flags:
++ ext = mozpath.splitext(f)[1]
++ yield PerSourceFlag(sandbox, f, sources[f].flags)
++@@ -458,7 +525,7 @@ class TreeMetadataEmitter(LoggingMixin):
++ sandbox['TOPSRCDIR']))
++ install_prefix = mozpath.join(install_root, install_subdir)
++
++- try:
+++ if 1: #try:
++ m = manifestparser.TestManifest(manifests=[path], strict=True)
++ defaults = m.manifest_defaults[os.path.normpath(path)]
++ if not m.tests and not 'support-files' in defaults:
++@@ -475,8 +542,10 @@ class TreeMetadataEmitter(LoggingMixin):
++ if filter_inactive:
++ # We return tests that don't exist because we want manifests
++ # defining tests that don't exist to result in error.
++- filtered = m.active_tests(exists=False, disabled=False,
++- **self.mozinfo)
+++ #print (self.mozinfo)
+++ filtered = []
+++ #FIXME filtered = m.active_tests(exists=False, disabled=False,
+++ # **self.mozinfo)
++
++ missing = [t['name'] for t in filtered if not os.path.exists(t['path'])]
++ if missing:
++@@ -586,10 +655,10 @@ class TreeMetadataEmitter(LoggingMixin):
++ obj.external_installs.add(mozpath.join(out_dir, f))
++
++ yield obj
++- except (AssertionError, Exception):
++- raise SandboxValidationError('Error processing test '
++- 'manifest file %s: %s' % (path,
++- '\n'.join(traceback.format_exception(*sys.exc_info()))))
+++ #except (AssertionError, Exception):
+++ # raise SandboxValidationError('Error processing test '
+++ # 'manifest file %s: %s' % (path,
+++ # '\n'.join(traceback.format_exception(*sys.exc_info()))))
++
++ def _emit_directory_traversal_from_sandbox(self, sandbox):
++ o = DirectoryTraversal(sandbox)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py 2014-10-24 11:41:35.490880096 -0600
++@@ -1,20 +1,128 @@
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++ import gyp
++ import sys
++ import time
++ import os
++ import mozpack.path as mozpath
++ from mozpack.files import FileFinder
++-from .sandbox import (
+++from sandbox import (
++ alphabetical_sorted,
++ GlobalNamespace,
++ )
++-from .sandbox_symbols import VARIABLES
++-from .reader import SandboxValidationError
+++from sandbox_symbols import VARIABLES
+++from reader import SandboxValidationError
++
++ # Define this module as gyp.generator.mozbuild so that gyp can use it
++ # as a generator under the name "mozbuild".
++@@ -37,7 +145,7 @@ generator_default_variables = {
++ for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
++ 'LIB_DIR', 'SHARED_LIB_DIR']:
++ # Some gyp steps fail if these are empty(!).
++- generator_default_variables[dirname] = b'dir'
+++ generator_default_variables[dirname] = 'dir'
++
++ for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
++ 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
++@@ -45,7 +153,7 @@ for unused in ['RULE_INPUT_PATH', 'RULE_
++ 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
++ 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
++ 'LINKER_SUPPORTS_ICF']:
++- generator_default_variables[unused] = b''
+++ generator_default_variables[unused] = ''
++
++
++ class GypSandbox(GlobalNamespace):
++@@ -91,9 +199,9 @@ def read_from_gyp(config, path, output,
++ str_vars = dict((name, encode(value)) for name, value in vars.items())
++
++ params = {
++- b'parallel': False,
++- b'generator_flags': {},
++- b'build_files': [path],
+++ 'parallel': False,
+++ 'generator_flags': {},
+++ 'build_files': [path],
++ }
++
++ # Files that gyp_chromium always includes
++@@ -104,7 +212,7 @@ def read_from_gyp(config, path, output,
++
++ # Read the given gyp file and its dependencies.
++ generator, flat_list, targets, data = \
++- gyp.Load([path], format=b'mozbuild',
+++ gyp.Load([path], format='mozbuild',
++ default_variables=str_vars,
++ includes=includes,
++ depth=encode(mozpath.dirname(path)),
++@@ -113,7 +221,7 @@ def read_from_gyp(config, path, output,
++ # Process all targets from the given gyp files and its dependencies.
++ # The path given to AllTargets needs to use os.sep, while the frontend code
++ # gives us paths normalized with forward slash separator.
++- for target in gyp.common.AllTargets(flat_list, targets, path.replace(b'/', os.sep)):
+++ for target in gyp.common.AllTargets(flat_list, targets, path.replace('/', os.sep)):
++ build_file, target_name, toolset = gyp.common.ParseQualifiedTarget(target)
++ # The list of included files returned by gyp are relative to build_file
++ included_files = [mozpath.abspath(mozpath.join(mozpath.dirname(build_file), f))
++@@ -122,7 +230,8 @@ def read_from_gyp(config, path, output,
++ sandbox = GypSandbox(mozpath.abspath(build_file), included_files)
++ sandbox.config = config
++
++- with sandbox.allow_all_writes() as d:
+++ d = sandbox.allow_all_writes()
+++ if 1:
++ topsrcdir = d['TOPSRCDIR'] = config.topsrcdir
++ d['TOPOBJDIR'] = config.topobjdir
++ relsrcdir = d['RELATIVEDIR'] = mozpath.relpath(mozpath.dirname(build_file), config.topsrcdir)
++@@ -143,10 +252,11 @@ def read_from_gyp(config, path, output,
++ d['OBJDIR'] = mozpath.join(output, reldir, subdir)
++ d['IS_GYP_DIR'] = True
++
+++ #d.__exit__(0, 0, 0)
++ spec = targets[target]
++
++ # Derive which gyp configuration to use based on MOZ_DEBUG.
++- c = 'Debug' if config.substs['MOZ_DEBUG'] else 'Release'
+++ c = ('Release', 'Debug')[config.substs['MOZ_DEBUG'] == '1']
++ if c not in spec['configurations']:
++ raise RuntimeError('Missing %s gyp configuration for target %s '
++ 'in %s' % (c, target_name, build_file))
++@@ -186,9 +296,11 @@ def read_from_gyp(config, path, output,
++ for include in target_conf.get('include_dirs', []):
++ sandbox['LOCAL_INCLUDES'] += [include]
++
++- with sandbox.allow_all_writes() as d:
+++ d = sandbox.allow_all_writes()
+++ if 1:
++ d['EXTRA_ASSEMBLER_FLAGS'] = target_conf.get('asflags_mozilla', [])
++ d['EXTRA_COMPILE_FLAGS'] = target_conf.get('cflags_mozilla', [])
+++ #d.__exit__(0, 0, 0)
++ else:
++ # Ignore other types than static_library because we don't have
++ # anything using them, and we're not testing them. They can be
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py 2014-10-24 11:41:35.490880096 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ from mach.decorators import (
++ CommandArgument,
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/reader.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/reader.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/reader.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/reader.py 2014-10-24 11:41:35.491880091 -0600
++@@ -20,8 +20,9 @@ execution.
++ The BuildReader contains basic logic for traversing a tree of mozbuild files.
++ It does this by examining specific variables populated during execution.
++ """
++-
++-from __future__ import print_function, unicode_literals
+++import sys
+++def print24(msg, file=sys.stdout, end='\n'):
+++ file.write(msg + end)
++
++ import logging
++ import os
++@@ -30,8 +31,8 @@ import time
++ import traceback
++ import types
++
++-from collections import OrderedDict
++-from io import StringIO
+++from mycollections import OrderedDict
+++import StringIO
++
++ from mozbuild.util import (
++ ReadOnlyDefaultDict,
++@@ -43,25 +44,25 @@ from mozbuild.backend.configenvironment
++ from mozpack.files import FileFinder
++ import mozpack.path as mozpath
++
++-from .data import (
+++from data import (
++ AndroidEclipseProjectData,
++ JavaJarData,
++ )
++
++-from .sandbox import (
+++from sandbox import (
++ SandboxError,
++ SandboxExecutionError,
++ SandboxLoadError,
++ Sandbox,
++ )
++
++-from .sandbox_symbols import (
+++from sandbox_symbols import (
++ FUNCTIONS,
++ VARIABLES,
++ )
++
++-if sys.version_info.major == 2:
++- text_type = unicode
+++if sys.version_info[0] == 2:
+++ text_type = str
++ type_type = types.TypeType
++ else:
++ text_type = str
++@@ -69,7 +70,9 @@ else:
++
++
++ def log(logger, level, action, params, formatter):
++- logger.log(level, formatter, extra={'action': action, 'params': params})
+++ #print(action, formatter)
+++ # logger.log(level, formatter, extra={'action': action, 'params': params})
+++ logger.log(level, formatter, action, params)
++
++
++ def is_read_allowed(path, config):
++@@ -124,6 +127,7 @@ class MozbuildSandbox(Sandbox):
++ the path of the main mozbuild file that is being executed. It is used
++ to compute encountered relative paths.
++ """
+++ #print path, config
++ Sandbox.__init__(self, allowed_variables=VARIABLES)
++
++ self._log = logging.getLogger(__name__)
++@@ -177,7 +181,8 @@ class MozbuildSandbox(Sandbox):
++ config.topobjdir = topobjdir
++ self.config = config
++
++- with self._globals.allow_all_writes() as d:
+++ d = self._globals.allow_all_writes()
+++ if 1:
++ d['TOPSRCDIR'] = topsrcdir
++ d['TOPOBJDIR'] = topobjdir
++ d['RELATIVEDIR'] = reldir
++@@ -282,7 +287,8 @@ class MozbuildSandbox(Sandbox):
++
++ def _add_tier_directory(self, tier, reldir, static=False, external=False):
++ """Register a tier directory with the build."""
++- if isinstance(reldir, text_type):
+++ #if isinstance(reldir, text_type):
+++ if isinstance(reldir, str):
++ reldir = [reldir]
++
++ if not tier in self['TIERS']:
++@@ -292,7 +298,13 @@ class MozbuildSandbox(Sandbox):
++ 'external': [],
++ }
++
++- key = 'static' if static else 'external' if external else 'regular'
+++ key = None
+++ if static:
+++ key = 'static'
+++ elif external:
+++ key = 'external'
+++ else:
+++ key = 'regular'
++ if external and static:
++ raise Exception('Only one of external or static can be set at the '
++ 'same time')
++@@ -336,7 +348,7 @@ class MozbuildSandbox(Sandbox):
++
++ def _warning(self, message):
++ # FUTURE consider capturing warnings in a variable instead of printing.
++- print('WARNING: %s' % message, file=sys.stderr)
+++ print24('WARNING: %s' % message, file=sys.stderr)
++
++ def _error(self, message):
++ raise SandboxCalledError(self._execution_stack, message)
++@@ -671,13 +683,13 @@ class BuildReader(object):
++ # In the future, we may traverse moz.build files by looking
++ # for DIRS references in the AST, even if a directory is added behind
++ # a conditional. For now, just walk the filesystem.
++- ignore = {
+++ ignore = (
++ # Ignore fake moz.build files used for testing moz.build.
++ 'python/mozbuild/mozbuild/test',
++
++ # Ignore object directories.
++ 'obj*',
++- }
+++ )
++
++ finder = FileFinder(self.topsrcdir, find_executables=False,
++ ignore=ignore)
++@@ -722,28 +734,28 @@ class BuildReader(object):
++ descend=descend, metadata=metadata):
++ yield s
++
++- except BuildReaderError as bre:
++- raise bre
+++ #except BuildReaderError, bre:
+++ # raise bre
++
++- except SandboxCalledError as sce:
+++ except SandboxCalledError, sce:
++ raise BuildReaderError(list(self._execution_stack),
++ sys.exc_info()[2], sandbox_called_error=sce)
++
++- except SandboxExecutionError as se:
++- raise BuildReaderError(list(self._execution_stack),
++- sys.exc_info()[2], sandbox_exec_error=se)
++-
++- except SandboxLoadError as sle:
++- raise BuildReaderError(list(self._execution_stack),
++- sys.exc_info()[2], sandbox_load_error=sle)
++-
++- except SandboxValidationError as ve:
++- raise BuildReaderError(list(self._execution_stack),
++- sys.exc_info()[2], validation_error=ve)
++-
++- except Exception as e:
++- raise BuildReaderError(list(self._execution_stack),
++- sys.exc_info()[2], other_error=e)
+++ #except SandboxExecutionError, se:
+++ # raise BuildReaderError(list(self._execution_stack),
+++ # sys.exc_info()[2], sandbox_exec_error=se)
+++
+++ #except SandboxLoadError, sle:
+++ # raise BuildReaderError(list(self._execution_stack),
+++ # sys.exc_info()[2], sandbox_load_error=sle)
+++
+++ #except SandboxValidationError, ve:
+++ # raise BuildReaderError(list(self._execution_stack),
+++ # sys.exc_info()[2], validation_error=ve)
+++
+++ #except Exception, e:
+++ # raise BuildReaderError(list(self._execution_stack),
+++ # sys.exc_info()[2], other_error=e)
++
++ def _read_mozbuild(self, path, config, read_tiers, filesystem_absolute,
++ descend, metadata):
++@@ -760,8 +772,14 @@ class BuildReader(object):
++
++ time_start = time.time()
++ sandbox = MozbuildSandbox(config, path, metadata=metadata)
+++ #print("exec file vvvv %s" % path)
+++ #print(sandbox)
+++ #print(dir(sandbox))
+++
++ sandbox.exec_file(path, filesystem_absolute=filesystem_absolute)
++ sandbox.execution_time = time.time() - time_start
+++ #print("exec file ^^^ %s" % path)
+++
++
++ if self._sandbox_post_eval_cb:
++ self._sandbox_post_eval_cb(sandbox)
++@@ -778,7 +796,7 @@ class BuildReader(object):
++ 'The %s variable%s not allowed in such directories.'
++ % (sandbox['RELATIVEDIR'], var, metadata['parent'],
++ ' and '.join(', '.join(matches).rsplit(', ', 1)),
++- 's are' if len(matches) > 1 else ' is'))
+++ ('is', 's are')[len(matches) > 1]))
++
++ # We first collect directories populated in variables.
++ dir_vars = ['DIRS', 'PARALLEL_DIRS', 'TOOL_DIRS']
++@@ -803,7 +821,7 @@ class BuildReader(object):
++ # We could emit the parent sandbox before processing gyp
++ # configuration, but we need to add the gyp objdirs to that sandbox
++ # first.
++- from .gyp_reader import read_from_gyp
+++ from gyp_reader import read_from_gyp
++ non_unified_sources = set()
++ for s in gyp_dir.non_unified_sources:
++ source = mozpath.normpath(mozpath.join(curdir, s))
++@@ -842,6 +860,9 @@ class BuildReader(object):
++ # It's very tempting to use a set here. Unfortunately, the recursive
++ # make backend needs order preserved. Once we autogenerate all backend
++ # files, we should be able to convert this to a set.
+++ #print("traverse")
+++
+++ #print "DIRS in recurse: %s" % dirs
++ recurse_info = OrderedDict()
++ for var, var_dirs in dirs:
++ for d in var_dirs:
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py 2014-10-24 11:41:35.491880091 -0600
++@@ -20,13 +20,13 @@ KeyError are machine parseable. This mac
++ user-friendly error messages in the case of errors.
++ """
++
++-from __future__ import unicode_literals
+++
++
++ import copy
++ import os
++ import sys
++
++-from contextlib import contextmanager
+++
++
++ from mozbuild.util import (
++ ReadOnlyDefaultDict,
++@@ -83,9 +83,11 @@ class GlobalNamespace(dict):
++ arbitrary values. e.g.
++
++ ns = GlobalNamespace()
++- with ns.allow_all_writes():
+++ ns.allow_all_writes().__enter__()
+++ if 1:
++ ns['foo'] = True
++
+++ ns.allow_all_writes().__exit__(0, 0, 0)
++ ns['bar'] = True # KeyError raised.
++ """
++
++@@ -128,13 +130,21 @@ class GlobalNamespace(dict):
++ self._allow_one_mutation = set()
++
++ def __getitem__(self, name):
+++ import traceback
++ try:
+++ #print(dir(self))
+++ #traceback.print_stack()
++ return dict.__getitem__(self, name)
++ except KeyError:
+++ #print self
+++ #print "Key error with", name
+++ #print "END OF KEY ERROR"
+++ #traceback.print_stack()
++ pass
++
++ # The variable isn't present yet. Fall back to VARIABLES.
++ default = self._allowed_variables.get(name, None)
+++ #print "default ", default
++ if default is None:
++ self.last_name_error = KeyError('global_ns', 'get_unknown', name)
++ raise self.last_name_error
++@@ -143,16 +153,18 @@ class GlobalNamespace(dict):
++ # not a class that can be called), then it is actually a rule to
++ # generate the default that should be used.
++ default = default[0]
+++ #print "default2 ", default
++ if issubclass(default, SandboxDerivedValue):
++ value = default(self)
++ else:
++ value = default()
++-
+++ #print "value", value, value.__class__
++ dict.__setitem__(self, name, value)
++ return dict.__getitem__(self, name)
++
++ def __setitem__(self, name, value):
++- if self._allow_all_writes:
+++ #if self._allow_all_writes:
+++ if 1: #if self._allow_all_writes:
++ dict.__setitem__(self, name, value)
++ self._allow_one_mutation.add(name)
++ return
++@@ -198,7 +210,7 @@ class GlobalNamespace(dict):
++
++ dict.__setitem__(self, name, value)
++
++- @contextmanager
+++ #@contextmanager
++ def allow_all_writes(self):
++ """Allow any variable to be written to this instance.
++
++@@ -208,8 +220,9 @@ class GlobalNamespace(dict):
++ whitelisted mutations.
++ """
++ self._allow_all_writes = True
++- yield self
++- self._allow_all_writes = False
+++ return self
+++ #yield self
+++ #self._allow_all_writes = False
++
++ # dict.update doesn't call our __setitem__, so we have to override it.
++ def update(self, other):
++@@ -337,14 +350,23 @@ class Sandbox(object):
++
++ source = None
++
+++ #try:
++ try:
++- with open(path, 'rt') as fd:
++- source = fd.read()
++- except Exception as e:
+++ fd = open(path, 'rt')
+++ source = fd.read()
+++ fd.close()
+++ except Exception, e:
+++ #print "Cannot read %s" % path
++ raise SandboxLoadError(list(self._execution_stack),
++ sys.exc_info()[2], read_error=path)
++
++ self.exec_source(source, path)
+++ #except Exception, e:
+++ # pass
+++ #except Exception, e:
+++ # raise SandboxLoadError(list(self._execution_stack),
+++ # sys.exc_info()[2], read_error=path)
+++
++
++ def exec_source(self, source, path):
++ """Execute Python code within a string.
++@@ -371,10 +393,12 @@ class Sandbox(object):
++ # compile() inherits the __future__ from the module by default. We
++ # do want Unicode literals.
++ code = compile(source, path, 'exec')
+++ #print self._globals
++ exec(code, self._globals, self._locals)
++- except SandboxError as e:
+++ except SandboxError, e:
+++ self._execution_stack.pop()
++ raise e
++- except NameError as e:
+++ except NameError, e:
++ # A NameError is raised when a local or global could not be found.
++ # The original KeyError has been dropped by the interpreter.
++ # However, we should have it cached in our namespace instances!
++@@ -389,17 +413,20 @@ class Sandbox(object):
++ elif self._locals.last_name_error is not None:
++ actual = self._locals.last_name_error
++
+++ self._execution_stack.pop()
++ raise SandboxExecutionError(list(self._execution_stack),
++ type(actual), actual, sys.exc_info()[2])
++
++- except Exception as e:
++- # Need to copy the stack otherwise we get a reference and that is
++- # mutated during the finally.
++- exc = sys.exc_info()
++- raise SandboxExecutionError(list(self._execution_stack), exc[0],
++- exc[1], exc[2])
++- finally:
++- self._execution_stack.pop()
+++ #except Exception, e:
+++ # # Need to copy the stack otherwise we get a reference and that is
+++ # # mutated during the finally.
+++ # exc = sys.exc_info()
+++ # l = list(self._execution_stack)
+++ # self._execution_stack.pop()
+++ # raise SandboxExecutionError(l, exc[0],
+++ # exc[1], exc[2])
+++ #finally:
+++ self._execution_stack.pop()
++
++ # Dict interface proxies reads to global namespace.
++ def __len__(self):
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox_symbols.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox_symbols.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/frontend/sandbox_symbols.py 2014-10-24 11:41:35.491880091 -0600
++@@ -15,20 +15,21 @@ If you are looking for the absolute auth
++ the Sandbox consists of, you've come to the right place.
++ """
++
++-from __future__ import unicode_literals
++
++-from collections import OrderedDict
+++
+++from ordereddict import OrderedDict
++ from mozbuild.util import (
++ HierarchicalStringList,
++ HierarchicalStringListWithFlagsFactory,
++ StrictOrderingOnAppendList,
++ StrictOrderingOnAppendListWithFlagsFactory,
++ )
++-from .sandbox import SandboxDerivedValue
+++from sandbox import SandboxDerivedValue
++ from types import StringTypes
++
+++str_type = str
++
++-class FinalTargetValue(SandboxDerivedValue, unicode):
+++class FinalTargetValue(SandboxDerivedValue, str_type):
++ def __new__(cls, sandbox, value=""):
++ if not value:
++ value = 'dist/'
++@@ -38,7 +39,7 @@ class FinalTargetValue(SandboxDerivedVal
++ value += 'bin'
++ if sandbox['DIST_SUBDIR']:
++ value += '/' + sandbox['DIST_SUBDIR']
++- return unicode.__new__(cls, value)
+++ return str_type.__new__(cls, value)
++
++
++ # This defines the set of mutable global variables.
++@@ -217,7 +218,7 @@ VARIABLES = {
++ files will be installed in the ``/components`` directory of the distribution.
++ """, 'libs'),
++
++- 'FINAL_LIBRARY': (unicode, unicode,
+++ 'FINAL_LIBRARY': (str_type, str_type,
++ """Library in which the objects of the current directory will be linked.
++
++ This variable contains the name of a library, defined elsewhere with
++@@ -276,7 +277,7 @@ VARIABLES = {
++ likely go away.
++ """, None),
++
++- 'HOST_LIBRARY_NAME': (unicode, unicode,
+++ 'HOST_LIBRARY_NAME': (str_type, str_type,
++ """Name of target library generated when cross compiling.
++ """, 'binaries'),
++
++@@ -287,7 +288,7 @@ VARIABLES = {
++ populated by calling add_java_jar().
++ """, 'binaries'),
++
++- 'JS_MODULES_PATH': (unicode, unicode,
+++ 'JS_MODULES_PATH': (str_type, str_type,
++ """Sub-directory of ``$(FINAL_TARGET)`` to install
++ ``EXTRA_JS_MODULES``.
++
++@@ -297,7 +298,7 @@ VARIABLES = {
++ ``$(FINAL_TARGET)/modules``.
++ """, None),
++
++- 'LIBRARY_NAME': (unicode, unicode,
+++ 'LIBRARY_NAME': (str_type, str_type,
++ """The name of the library generated for a directory.
++
++ In ``example/components/moz.build``,::
++@@ -335,25 +336,25 @@ VARIABLES = {
++
++ This variable contains a list of system libaries to link against.
++ """, None),
++- 'RCFILE': (unicode, unicode,
+++ 'RCFILE': (str_type, str_type,
++ """The program .rc file.
++
++ This variable can only be used on Windows.
++ """, None),
++
++- 'RESFILE': (unicode, unicode,
+++ 'RESFILE': (str_type, str_type,
++ """The program .res file.
++
++ This variable can only be used on Windows.
++ """, None),
++
++- 'RCINCLUDE': (unicode, unicode,
+++ 'RCINCLUDE': (str_type, str_type,
++ """The resource script file to be included in the default .res file.
++
++ This variable can only be used on Windows.
++ """, None),
++
++- 'DEFFILE': (unicode, unicode,
+++ 'DEFFILE': (str_type, str_type,
++ """The program .def (module definition) file.
++
++ This variable can only be used on Windows.
++@@ -483,7 +484,7 @@ VARIABLES = {
++ EXPORTS.mozilla.dom += ['bar.h']
++ """, None),
++
++- 'PROGRAM' : (unicode, unicode,
+++ 'PROGRAM' : (str_type, str_type,
++ """Compiled executable name.
++
++ If the configuration token ``BIN_SUFFIX`` is set, its value will be
++@@ -491,7 +492,7 @@ VARIABLES = {
++ ``BIN_SUFFIX``, ``PROGRAM`` will remain unchanged.
++ """, 'binaries'),
++
++- 'HOST_PROGRAM' : (unicode, unicode,
+++ 'HOST_PROGRAM' : (str_type, str_type,
++ """Compiled host executable name.
++
++ If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will be
++@@ -523,7 +524,7 @@ VARIABLES = {
++ files.
++ """, 'libs'),
++
++- 'XPIDL_MODULE': (unicode, unicode,
+++ 'XPIDL_MODULE': (str_type, str_type,
++ """XPCOM Interface Definition Module Name.
++
++ This is the name of the ``.xpt`` file that is created by linking
++@@ -618,14 +619,14 @@ VARIABLES = {
++ """, None),
++
++ # The following variables are used to control the target of installed files.
++- 'XPI_NAME': (unicode, unicode,
+++ 'XPI_NAME': (str_type, str_type,
++ """The name of an extension XPI to generate.
++
++ When this variable is present, the results of this directory will end up
++ being packaged into an extension instead of the main dist/bin results.
++ """, 'libs'),
++
++- 'DIST_SUBDIR': (unicode, unicode,
+++ 'DIST_SUBDIR': (str_type, str_type,
++ """The name of an alternate directory to install files to.
++
++ When this variable is present, the results of this directory will end up
++@@ -633,7 +634,7 @@ VARIABLES = {
++ otherwise be placed.
++ """, 'libs'),
++
++- 'FINAL_TARGET': (FinalTargetValue, unicode,
+++ 'FINAL_TARGET': (FinalTargetValue, str_type,
++ """The name of the directory to install targets to.
++
++ The directory is relative to the top of the object directory. The
++@@ -645,7 +646,7 @@ VARIABLES = {
++
++ 'GYP_DIRS': (StrictOrderingOnAppendListWithFlagsFactory({
++ 'variables': dict,
++- 'input': unicode,
+++ 'input': str_type,
++ 'sandbox_vars': dict,
++ 'non_unified_sources': StrictOrderingOnAppendList,
++ }), list,
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/html_build_viewer.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/html_build_viewer.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/html_build_viewer.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/html_build_viewer.py 2014-10-24 11:41:35.491880091 -0600
++@@ -4,7 +4,7 @@
++
++ # This module contains code for running an HTTP server to view build info.
++
++-from __future__ import unicode_literals
+++
++
++ import BaseHTTPServer
++ import json
++@@ -36,9 +36,11 @@ class HTTPHandler(BaseHTTPServer.BaseHTT
++ self.send_header('Content-Type', 'application/json; charset=utf-8')
++ self.end_headers()
++
++- with open(s.json_files[key], 'rb') as fh:
+++ fh = open(s.json_files[key], 'rb')
+++ if 1:
++ self.wfile.write(fh.read())
++
+++ fh.close()
++ return
++
++ if p == '/':
++@@ -78,10 +80,12 @@ class HTTPHandler(BaseHTTPServer.BaseHTT
++ self.send_header('Content-Type', ct)
++ self.end_headers()
++
++- with open(local_path, 'rb') as fh:
+++ fh = open(local_path, 'rb')
+++ if 1:
++ self.wfile.write(fh.read())
++
++
+++ fh.close()
++ class BuildViewerServer(object):
++ def __init__(self, address='localhost', port=0):
++ # TODO use pkg_resources to obtain HTML resources.
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/jar.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/jar.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/jar.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/jar.py 2014-10-24 11:41:35.492880087 -0600
++@@ -165,13 +165,14 @@ class JarMaker(object):
++ 'chrome.manifest')
++
++ if self.useJarfileManifest:
+++ #print chromebasepath
++ self.updateManifest(jarPath + '.manifest',
++- chromebasepath.format(''), register)
+++ chromebasepath %(''), register)
++ addEntriesToListFile(chromeManifest,
++- ['manifest chrome/{0}.manifest'.format(os.path.basename(jarPath))])
+++ ['manifest chrome/%s.manifest' % (os.path.basename(jarPath))])
++ if self.useChromeManifest:
++ self.updateManifest(chromeManifest,
++- chromebasepath.format('chrome/'),
+++ chromebasepath % ('chrome/'),
++ register)
++
++ # If requested, add a root chrome manifest entry (assumed to be in the parent directory
++@@ -289,7 +290,7 @@ class JarMaker(object):
++ # {0} is getting replaced with chrome/ for chrome.manifest, and with
++ # an empty string for jarfile.manifest
++
++- chromebasepath = '{0}' + os.path.basename(jarfile)
+++ chromebasepath = '%s' + os.path.basename(jarfile)
++ if self.outputFormat == 'jar':
++ chromebasepath = 'jar:' + chromebasepath + '.jar!'
++ chromebasepath += '/'
++@@ -382,7 +383,7 @@ class JarMaker(object):
++ if realsrc is None:
++ if jf is not None:
++ jf.close()
++- raise RuntimeError('File "{0}" not found in {1}'.format(src,
+++ raise RuntimeError('File "%s" not found in %s' % (src,
++ ', '.join(src_base)))
++ if m.group('optPreprocess'):
++ outf = outHelper.getOutput(out)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/mach_commands.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/mach_commands.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/mach_commands.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/mach_commands.py 2014-10-24 11:41:35.492880087 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import itertools
++ import logging
++@@ -183,9 +187,11 @@ class BuildProgressFooter(object):
++
++ write_pieces.append(part)
++ written += len(part)
++- with self._t.location():
+++ self._t.location().__enter__()
+++ if 1:
++ self._t.move(self._t.height-1,0)
++ self._fh.write(''.join(write_pieces))
+++ self._t.location().__exit__(0, 0, 0)
++ self._fh.flush()
++
++
++@@ -286,7 +292,8 @@ class Build(MachCommandBase):
++ monitor = self._spawn(BuildMonitor)
++ monitor.init(warnings_path)
++
++- with BuildOutputManager(self.log_manager, monitor) as output:
+++ output = BuildOutputManager(self.log_manager, monitor).__enter__()
+++ if 1:
++ monitor.start()
++
++ if what:
++@@ -326,8 +333,10 @@ class Build(MachCommandBase):
++ add_extra_dependencies)
++ depfile = os.path.join(self.topsrcdir, 'build',
++ 'dumbmake-dependencies')
++- with open(depfile) as f:
+++ f = open(depfile)
+++ if 1:
++ dm = dependency_map(f.readlines())
+++ f.close()
++ new_pairs = list(add_extra_dependencies(target_pairs, dm))
++ self.log(logging.DEBUG, 'dumbmake',
++ {'target_pairs': target_pairs,
++@@ -373,6 +382,7 @@ class Build(MachCommandBase):
++
++ monitor.finish(record_usage=status==0)
++
+++ output.__exit__(0, 0, 0)
++ high_finder, finder_percent = monitor.have_high_finder_usage()
++ if high_finder:
++ print(FINDER_SLOW_MESSAGE % finder_percent)
++@@ -390,7 +400,7 @@ class Build(MachCommandBase):
++ '-message', 'Build complete'], ensure_exit_code=False)
++ except which.WhichError:
++ pass
++- except Exception as e:
+++ except Exception, e:
++ self.log(logging.WARNING, 'notifier-failed', {'error':
++ e.message}, 'Notification center failed: {error}')
++
++@@ -478,7 +488,7 @@ class Build(MachCommandBase):
++ try:
++ self.remove_objdir()
++ return 0
++- except OSError as e:
+++ except OSError, e:
++ if sys.platform.startswith('win'):
++ if isinstance(e, WindowsError) and e.winerror in (5,32):
++ self.log(logging.ERROR, 'file_access_error', {'error': e},
++@@ -598,13 +608,13 @@ class GTestCommands(MachCommandBase):
++ # https://code.google.com/p/googletest/wiki/AdvancedGuide#Running_Test_Programs:_Advanced_Options
++ gtest_env = {b'GTEST_FILTER': gtest_filter}
++
++- gtest_env[b"MOZ_RUN_GTEST"] = b"True"
+++ gtest_env[b"MOZ_RUN_GTEST"] = "True"
++
++ if shuffle:
++- gtest_env[b"GTEST_SHUFFLE"] = b"True"
+++ gtest_env[b"GTEST_SHUFFLE"] = "True"
++
++ if tbpl_parser:
++- gtest_env[b"MOZ_TBPL_PARSER"] = b"True"
+++ gtest_env[b"MOZ_TBPL_PARSER"] = "True"
++
++ if jobs == 1:
++ return self.run_process([app_path, "-unittest"],
++@@ -728,7 +738,7 @@ class RunProgram(MachCommandBase):
++ def run(self, params, remote, background):
++ try:
++ args = [self.get_binary_path('app')]
++- except Exception as e:
+++ except Exception, e:
++ print("It looks like your program isn't built.",
++ "You can run |mach build| to build it.")
++ print(e)
++@@ -772,7 +782,7 @@ class DebugProgram(MachCommandBase):
++ if debugger:
++ try:
++ debugger = which.which(debugger)
++- except Exception as e:
+++ except Exception, e:
++ print("You don't have %s in your PATH" % (debugger))
++ print(e)
++ return 1
++@@ -784,7 +794,7 @@ class DebugProgram(MachCommandBase):
++ try:
++ debugger = which.which('lldb')
++ use_lldb = True
++- except Exception as e:
+++ except Exception, e:
++ print("You don't have gdb or lldb in your PATH")
++ print(e)
++ return 1
++@@ -803,7 +813,7 @@ class DebugProgram(MachCommandBase):
++
++ try:
++ binpath = self.get_binary_path('app')
++- except Exception as e:
+++ except Exception, e:
++ print("It looks like your program isn't built.",
++ "You can run |mach build| to build it.")
++ print(e)
++@@ -883,7 +893,7 @@ class Makefiles(MachCommandBase):
++ if not statements:
++ print(relpath)
++ except pymake.parser.SyntaxError:
++- print('Warning: Could not parse %s' % relpath, file=sys.stderr)
+++ print24('Warning: Could not parse %s' % relpath, file=sys.stderr)
++
++ def _makefile_ins(self):
++ for root, dirs, files in os.walk(self.topsrcdir):
++@@ -909,7 +919,7 @@ class MachDebug(MachCommandBase):
++
++ try:
++ mb = MozbuildObject.from_environment(cwd=self._mach_context.cwd)
++- except ObjdirMismatchException as e:
+++ except ObjdirMismatchException, e:
++ print('Ambiguous object directory detected. We detected that '
++ 'both %s and %s could be object directories. This is '
++ 'typically caused by having a mozconfig pointing to a '
++@@ -924,11 +934,11 @@ class MachDebug(MachCommandBase):
++ try:
++ mozconfig = mb.mozconfig
++ print('mozconfig path:\n\t%s' % mozconfig['path'])
++- except MozconfigFindException as e:
+++ except MozconfigFindException, e:
++ print('Unable to find mozconfig: %s' % e.message)
++ return 1
++
++- except MozconfigLoadException as e:
+++ except MozconfigLoadException, e:
++ print('Error loading mozconfig: %s' % e.path)
++ print(e.message)
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/makeutil.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/makeutil.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/makeutil.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/makeutil.py 2014-10-24 11:41:35.492880087 -0600
++@@ -5,7 +5,9 @@
++ import os
++ import re
++ from types import StringTypes
++-from collections import Iterable
+++import rhrebase
+++print dir(rhrebase)
+++from rhrebase import isIterable
++
++
++ class Makefile(object):
++@@ -101,19 +103,23 @@ class Rule(object):
++
++ def add_targets(self, targets):
++ '''Add additional targets to the rule.'''
++- assert isinstance(targets, Iterable) and not isinstance(targets, StringTypes)
+++ assert isIterable(targets) and not isinstance(targets, StringTypes)
++ self._targets.update(targets)
++ return self
++
++ def add_dependencies(self, deps):
++ '''Add dependencies to the rule.'''
++- assert isinstance(deps, Iterable) and not isinstance(deps, StringTypes)
+++ #import traceback
+++ #traceback.print_stack()
+++ #print (deps)
+++ #print (dir(deps))
+++ assert isIterable(deps) and not isinstance(deps, StringTypes)
++ self._dependencies.update(deps)
++ return self
++
++ def add_commands(self, commands):
++ '''Add commands to the rule.'''
++- assert isinstance(commands, Iterable) and not isinstance(commands, StringTypes)
+++ assert isIterable(commands) and not isinstance(commands, StringTypes)
++ self._commands.extend(commands)
++ return self
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/mozconfig.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/mozconfig.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/mozconfig.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/mozconfig.py 2014-10-24 11:41:35.493880083 -0600
++@@ -2,14 +2,14 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import filecmp
++ import os
++ import re
++ import subprocess
++
++-from collections import defaultdict
+++from mycollections import defaultdict
++ from mach.mixin.process import ProcessExecutionMixin
++
++
++@@ -215,9 +215,10 @@ class MozconfigLoader(ProcessExecutionMi
++ try:
++ # We need to capture stderr because that's where the shell sends
++ # errors if execution fails.
++- output = subprocess.check_output(args, stderr=subprocess.STDOUT,
++- cwd=self.topsrcdir, env=env)
++- except subprocess.CalledProcessError as e:
+++ output = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.topsrcdir, env=env).communicate()[0]
+++ #output = subprocess.check_output(args, stderr=subprocess.STDOUT,
+++ # cwd=self.topsrcdir, env=env)
+++ except subprocess.CalledProcessError, e:
++ lines = e.output.splitlines()
++
++ # Output before actual execution shouldn't be relevant.
++@@ -396,7 +397,11 @@ class MozconfigLoader(ProcessExecutionMi
++ current.append(value)
++ continue
++ else:
++- value = value[:-1] if has_quote else value
+++ #value = None
+++ if has_quote:
+++ value = value[:-1]
+++ else:
+++ value = value
++
++ assert name is not None
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/mozinfo.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/mozinfo.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/mozinfo.py.python3 2014-10-24 11:41:35.411880430 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/mozinfo.py 2014-10-24 11:41:35.493880083 -0600
++@@ -7,7 +7,7 @@
++
++ import os
++ import re
++-import json
+++import simplejson as json
++ import mozbuild.mozconfig as mozconfig
++
++ def build_dict(config, env=os.environ):
++@@ -36,7 +36,7 @@ def build_dict(config, env=os.environ):
++ known_os = {"Linux": "linux",
++ "WINNT": "win",
++ "Darwin": "mac",
++- "Android": "b2g" if substs["MOZ_WIDGET_TOOLKIT"] == "gonk" else "android"}
+++ "Android": ("android", "b2g")[substs["MOZ_WIDGET_TOOLKIT"] == "gonk"]}
++ if o in known_os:
++ d["os"] = known_os[o]
++ else:
++@@ -91,7 +91,7 @@ def build_dict(config, env=os.environ):
++ return d
++
++
++-def write_mozinfo(file, config, env=os.environ):
+++def write_mozinfo(_file, config, env=os.environ):
++ """Write JSON data about the configuration specified in config and an
++ environment variable dict to |file|, which may be a filename or file-like
++ object.
++@@ -99,8 +99,9 @@ def write_mozinfo(file, config, env=os.e
++ and what keys are produced.
++ """
++ build_conf = build_dict(config, env)
++- if isinstance(file, basestring):
++- with open(file, "w") as f:
++- json.dump(build_conf, f)
+++ if isinstance(_file, basestring):
+++ f = open(_file, "w")
+++ json.dump(build_conf, f)
+++ f.close()
++ else:
++- json.dump(build_conf, file)
+++ json.dump(build_conf, _file)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/preprocessor.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/preprocessor.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/preprocessor.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/preprocessor.py 2014-10-24 11:41:35.493880083 -0600
++@@ -241,7 +241,7 @@ class Expression:
++ self.offset = expression.offset
++ self.content = expression.content[:3]
++ def __str__(self):
++- return 'Unexpected content at offset {0}, "{1}"'.format(self.offset,
+++ return 'Unexpected content at offset %d, "%s"' % (self.offset,
++ self.content)
++
++ class Context(dict):
++@@ -320,9 +320,9 @@ class Preprocessor:
++
++ def warnUnused(self, file):
++ if self.actionLevel == 0:
++- sys.stderr.write('{0}: WARNING: no preprocessor directives found\n'.format(file))
+++ sys.stderr.write('%s: WARNING: no preprocessor directives found\n' % (file))
++ elif self.actionLevel == 1:
++- sys.stderr.write('{0}: WARNING: no useful preprocessor directives found\n'.format(file))
+++ sys.stderr.write('%s: WARNING: no useful preprocessor directives found\n' % (file))
++ pass
++
++ def setLineEndings(self, aLE):
++@@ -339,8 +339,9 @@ class Preprocessor:
++ """
++ self.marker = aMarker
++ if aMarker:
++- self.instruction = re.compile('{0}(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'
++- .format(aMarker),
+++ #self.instruction = re.compile('%s{0}(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'
+++ self.instruction = re.compile('%s(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'
+++ % aMarker,
++ re.U)
++ self.comment = re.compile(aMarker, re.U)
++ else:
++@@ -414,9 +415,7 @@ class Preprocessor:
++ self.writtenLines += 1
++ ln = self.context['LINE']
++ if self.writtenLines != ln:
++- self.out.write('//@line {line} "{file}"{le}'.format(line=ln,
++- file=self.context['FILE'],
++- le=self.LE))
+++ self.out.write('//@line %s "%s"%s' % (ln, self.context['FILE'], self.LE))
++ self.writtenLines = ln
++ filteredLine = self.applyFilters(aLine)
++ if filteredLine != aLine:
++@@ -436,7 +435,7 @@ class Preprocessor:
++ if dir:
++ try:
++ os.makedirs(dir)
++- except OSError as error:
+++ except OSError, error:
++ if error.errno != errno.EEXIST:
++ raise
++ return open(path, 'wb')
++@@ -468,8 +467,10 @@ class Preprocessor:
++
++ if includes:
++ for f in includes:
++- with open(f, 'rU') as input:
+++ input = open(f, 'rU')
+++ if 1:
++ self.processFile(input=input, output=out)
+++ input.close()
++ if depfile:
++ mk = Makefile()
++ mk.create_rule([options.output]).add_dependencies(self.includes)
++@@ -793,10 +794,12 @@ def preprocess(includes=[sys.stdin], def
++ defines=defines,
++ marker=marker)
++ for f in includes:
++- with open(f, 'rU') as input:
+++ input = open(f, 'rU')
+++ if 1:
++ pp.processFile(input=input, output=output)
++
++
+++ input.close()
++ # Keep this module independently executable.
++ if __name__ == "__main__":
++ pp = Preprocessor()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/pythonutil.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/pythonutil.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/pythonutil.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/pythonutil.py 2014-10-24 11:41:35.493880083 -0600
++@@ -1,4 +1,5 @@
++-# This Source Code Form is subject to the terms of the Mozilla Public
+++from rhrebase import any
+++#from rhrebase import any#from rhrebase import any#from rhrebase import any# This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/sphinx.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/sphinx.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/sphinx.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/sphinx.py 2014-10-24 11:41:35.493880083 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import absolute_import
+++
++
++ import importlib
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/common.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/common.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/common.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/common.py 2014-10-24 11:41:35.494880079 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import unittest
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py 2014-10-24 11:41:35.494880079 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import json
++ import os
++@@ -64,8 +64,10 @@ class TestAndroidEclipseBackend(BackendT
++ self.env = self._consume('android_eclipse', AndroidEclipseBackend)
++ self.assertExists('main3', '.classpath')
++ # This is brittle but simple.
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main3', '.classpath'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main3', '.classpath'), 'rt')
+++ if 1:
++ lines = fh.readlines()
+++ fh.__exit__(0, 0, 0)
++ lines = [line.strip() for line in lines]
++ self.assertIn('<classpathentry including="**/*.java" kind="src" path="a" />', lines)
++ self.assertIn('<classpathentry excluding="b/Excludes.java|b/Excludes2.java" including="**/*.java" kind="src" path="b" />', lines)
++@@ -76,14 +78,18 @@ class TestAndroidEclipseBackend(BackendT
++ self.env = self._consume('android_eclipse', AndroidEclipseBackend)
++
++ self.assertExists('library1', 'project.properties')
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'library1', 'project.properties'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'library1', 'project.properties'), 'rt')
+++ if 1:
++ lines = fh.readlines()
+++ fh.__exit__(0, 0, 0)
++ lines = [line.strip() for line in lines]
++ self.assertIn('android.library=true', lines)
++
++ self.assertExists('main1', 'project.properties')
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main1', 'project.properties'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main1', 'project.properties'), 'rt').__enter__()
+++ if 1:
++ lines = fh.readlines()
+++ fh.__exit__(0, 0, 0)
++ lines = [line.strip() for line in lines]
++ self.assertNotIn('android.library=true', lines)
++
++@@ -92,8 +98,10 @@ class TestAndroidEclipseBackend(BackendT
++ self.env = self._consume('android_eclipse', AndroidEclipseBackend)
++ self.assertExists('main4', '.classpath')
++ # This is brittle but simple.
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main4', '.classpath'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main4', '.classpath'), 'rt').__enter__()
+++ if 1:
++ lines = fh.readlines()
+++ fh.__exit__(0, 0, 0)
++ lines = [line.strip() for line in lines]
++ self.assertIn('<classpathentry combineaccessrules="false" kind="src" path="/library1" />', lines)
++
++@@ -102,8 +110,10 @@ class TestAndroidEclipseBackend(BackendT
++ self.env = self._consume('android_eclipse', AndroidEclipseBackend)
++ self.assertExists('main2', '.classpath')
++ # This is brittle but simple.
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main2', '.classpath'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main2', '.classpath'), 'rt').__enter__()
+++ if 1:
++ lines = fh.readlines()
+++ fh.close()
++ lines = [line.strip() for line in lines]
++ self.assertIn('<classpathentry exported="true" kind="lib" path="%s/main2/extra.jar" />' % self.env.topsrcdir, lines)
++
++@@ -112,8 +122,10 @@ class TestAndroidEclipseBackend(BackendT
++ self.env = self._consume('android_eclipse', AndroidEclipseBackend)
++ self.assertExists('main4', 'project.properties')
++ # This is brittle but simple.
++- with open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main4', 'project.properties'), 'rt') as fh:
+++ fh = open(mozpath.join(self.env.topobjdir, 'android_eclipse', 'main4', 'project.properties'), 'rt').__enter__()
+++ if 1:
++ lines = fh.readlines()
+++ fh.close()
++ lines = [line.strip() for line in lines]
++ self.assertIn('android.library.reference.1=library2', lines)
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py 2014-10-24 11:41:35.494880079 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import json
++ import os
++@@ -414,7 +414,8 @@ class TestRecursiveMakeBackend(BackendTe
++ all_tests_path = mozpath.join(env.topobjdir, 'all-tests.json')
++ self.assertTrue(os.path.exists(all_tests_path))
++
++- with open(all_tests_path, 'rt') as fh:
+++ fh = open(all_tests_path, 'rt')
+++ if 1:
++ o = json.load(fh)
++
++ self.assertIn('xpcshell.js', o)
++@@ -422,6 +423,7 @@ class TestRecursiveMakeBackend(BackendTe
++
++ self.assertEqual(len(o['xpcshell.js']), 1)
++
+++ fh.__exit__(0, 0, 0)
++ def test_test_manifest_pattern_matches_recorded(self):
++ """Pattern matches in test manifests' support-files should be recorded."""
++ env = self._consume('test-manifests-written', RecursiveMakeBackend)
++@@ -588,8 +590,7 @@ class TestRecursiveMakeBackend(BackendTe
++ for key, expected_rules in expected.iteritems():
++ backend_path = mozpath.join(key, 'backend.mk')
++ lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
++- found = [str for str in lines if
++- str.startswith('FINAL_TARGET') or str.startswith('XPI_NAME') or
+++ found = [str for str in lines if str.startswith('FINAL_TARGET') or str.startswith('XPI_NAME') or
++ str.startswith('DIST_SUBDIR')]
++ self.assertEqual(found, expected_rules)
++
++@@ -627,9 +628,11 @@ class TestRecursiveMakeBackend(BackendTe
++ def test_jar_manifests(self):
++ env = self._consume('jar-manifests', RecursiveMakeBackend)
++
++- with open(os.path.join(env.topobjdir, 'backend.mk'), 'rb') as fh:
+++ fh = open(os.path.join(env.topobjdir, 'backend.mk'), 'rb')
+++ if 1:
++ lines = fh.readlines()
++
+++ fh.__exit__(0, 0, 0)
++ lines = [line.rstrip() for line in lines]
++
++ self.assertIn('JAR_MANIFEST := %s/jar.mn' % env.topsrcdir, lines)
++@@ -646,9 +649,11 @@ class TestRecursiveMakeBackend(BackendTe
++ def test_android_eclipse(self):
++ env = self._consume('android_eclipse', RecursiveMakeBackend)
++
++- with open(mozpath.join(env.topobjdir, 'backend.mk'), 'rb') as fh:
+++ fh = open(mozpath.join(env.topobjdir, 'backend.mk'), 'rb').__enter__()
+++ if 1:
++ lines = fh.readlines()
++
+++ fh.close()
++ lines = [line.rstrip() for line in lines]
++
++ # Dependencies first.
++@@ -664,9 +669,11 @@ class TestRecursiveMakeBackend(BackendTe
++ self.assertIn(command_template % (stem, stem), lines)
++
++ # Projects declared in subdirectories.
++- with open(mozpath.join(env.topobjdir, 'subdir', 'backend.mk'), 'rb') as fh:
+++ fh = open(mozpath.join(env.topobjdir, 'subdir', 'backend.mk'), 'rb').__enter__()
+++ if 1:
++ lines = fh.readlines()
++
+++ fh.close()
++ lines = [line.rstrip() for line in lines]
++
++ self.assertIn('ANDROID_ECLIPSE_PROJECT_submain: subtarget1 subtarget2', lines)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py 2014-10-24 11:41:35.494880079 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from xml.dom.minidom import parse
++ import os
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/common.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/common.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/common.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/common.py 2014-10-24 11:41:35.495880074 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/compilation/test_warnings.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/compilation/test_warnings.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/compilation/test_warnings.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/compilation/test_warnings.py 2014-10-24 11:41:35.495880074 -0600
++@@ -181,9 +181,11 @@ class TestWarningsDatabase(unittest.Test
++
++ w['filename'] = 'DOES_NOT_EXIST'
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ db.insert(w)
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_pruning(self):
++ """Ensure old warnings are removed from database appropriately."""
++ db = WarningsDatabase()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py 2014-10-24 11:41:35.495880074 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import shutil
++@@ -37,9 +37,11 @@ class TestClobberer(unittest.TestCase):
++ def get_topsrcdir(self):
++ t = self.get_tempdir()
++ p = os.path.join(t, 'CLOBBER')
++- with open(p, 'a'):
+++ open(p, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(p, 'a').__exit__(0, 0, 0)
++ return t
++
++ def test_no_objdir(self):
++@@ -77,9 +79,11 @@ class TestClobberer(unittest.TestCase):
++ """If CLOBBER in topobjdir is newer, do nothing."""
++
++ c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
++- with open(c.obj_clobber, 'a'):
+++ open(c.obj_clobber, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(c.obj_clobber, 'a').__exit__(0, 0, 0)
++ required, performed, reason = c.maybe_do_clobber(os.getcwd(), True)
++ self.assertFalse(required)
++ self.assertFalse(performed)
++@@ -89,13 +93,17 @@ class TestClobberer(unittest.TestCase):
++ """If CLOBBER in topobjdir is older, we clobber."""
++
++ c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
++- with open(c.obj_clobber, 'a'):
+++ open(c.obj_clobber, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(c.obj_clobber, 'a').__exit__(0, 0, 0)
++ dummy_path = os.path.join(c.topobjdir, 'foo')
++- with open(dummy_path, 'a'):
+++ open(dummy_path, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(dummy_path, 'a').__exit__(0, 0, 0)
++ self.assertTrue(os.path.exists(dummy_path))
++
++ old_time = os.path.getmtime(c.src_clobber) - 60
++@@ -124,13 +132,17 @@ class TestClobberer(unittest.TestCase):
++ """If cwd is topobjdir, we can still clobber."""
++ c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
++
++- with open(c.obj_clobber, 'a'):
+++ open(c.obj_clobber, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(c.obj_clobber, 'a').__exit__(0, 0, 0)
++ dummy_file = os.path.join(c.topobjdir, 'dummy_file')
++- with open(dummy_file, 'a'):
+++ open(dummy_file, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(dummy_file, 'a').__exit__(0, 0, 0)
++ dummy_dir = os.path.join(c.topobjdir, 'dummy_dir')
++ os.mkdir(dummy_dir)
++
++@@ -154,9 +166,11 @@ class TestClobberer(unittest.TestCase):
++
++ c = Clobberer(self.get_topsrcdir(), self.get_tempdir())
++
++- with open(c.obj_clobber, 'a'):
+++ open(c.obj_clobber, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(c.obj_clobber, 'a').__exit__(0, 0, 0)
++ old_time = os.path.getmtime(c.src_clobber) - 60
++ os.utime(c.obj_clobber, (old_time, old_time))
++
++@@ -176,13 +190,17 @@ class TestClobberer(unittest.TestCase):
++ topobjdir = self.get_tempdir()
++
++ obj_clobber = os.path.join(topobjdir, 'CLOBBER')
++- with open(obj_clobber, 'a'):
+++ open(obj_clobber, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(obj_clobber, 'a').__exit__(0, 0, 0)
++ dummy_file = os.path.join(topobjdir, 'dummy_file')
++- with open(dummy_file, 'a'):
+++ open(dummy_file, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(dummy_file, 'a').__exit__(0, 0, 0)
++ self.assertTrue(os.path.exists(dummy_file))
++
++ old_time = os.path.getmtime(os.path.join(topsrcdir, 'CLOBBER')) - 60
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py 2014-10-24 11:41:35.495880074 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import unittest
++@@ -299,17 +299,21 @@ class TestEmitterBasic(unittest.TestCase
++ """A missing manifest file should result in an error."""
++ reader = self.reader('test-manifest-missing-manifest')
++
++- with self.assertRaisesRegexp(SandboxValidationError, 'IOError: Missing files'):
+++ self.assertRaisesRegexp(SandboxValidationError, 'IOError: Missing files').__enter__()
+++ if 1:
++ self.read_topsrcdir(reader)
++
+++ self.assertRaisesRegexp(SandboxValidationError, 'IOError: Missing files').__exit__(0, 0, 0)
++ def test_empty_test_manifest_rejected(self):
++ """A test manifest without any entries is rejected."""
++ reader = self.reader('test-manifest-empty')
++
++- with self.assertRaisesRegexp(SandboxValidationError, 'Empty test manifest'):
+++ self.assertRaisesRegexp(SandboxValidationError, 'Empty test manifest').__enter__()
+++ if 1:
++ self.read_topsrcdir(reader)
++
++
+++ self.assertRaisesRegexp(SandboxValidationError, 'Empty test manifest').__exit__(0, 0, 0)
++ def test_test_manifest_just_support_files(self):
++ """A test manifest with no tests but support-files is supported."""
++ reader = self.reader('test-manifest-just-support')
++@@ -592,10 +596,12 @@ class TestEmitterBasic(unittest.TestCase
++ self.assertTrue(os.path.isabs(obj.path))
++
++ def test_jar_manifests_multiple_files(self):
++- with self.assertRaisesRegexp(SandboxValidationError, 'limited to one value'):
+++ self.assertRaisesRegexp(SandboxValidationError, 'limited to one value').__enter__()
+++ if 1:
++ reader = self.reader('jar-manifests-multiple-files')
++ self.read_topsrcdir(reader)
++
+++ self.assertRaisesRegexp(SandboxValidationError, 'limited to one value').__exit__(0, 0, 0)
++ def test_xpidl_module_no_sources(self):
++ """XPIDL_MODULE without XPIDL_SOURCES should be rejected."""
++ with self.assertRaisesRegexp(SandboxValidationError, 'XPIDL_MODULE '
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py 2014-10-24 11:41:35.496880070 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import unittest
++
++@@ -27,9 +27,11 @@ class TestGlobalNamespace(unittest.TestC
++ # Lowercase keys should be rejected during normal operation.
++ ns = GlobalNamespace(allowed_variables=VARIABLES)
++
++- with self.assertRaises(KeyError) as ke:
+++ ke = self.assertRaises(KeyError).__enter__()
+++ if 1:
++ ns['foo'] = True
++
+++ ke.__exit__(0, 0, 0)
++ e = ke.exception.args
++ self.assertEqual(e[0], 'global_ns')
++ self.assertEqual(e[1], 'set_unknown')
++@@ -37,9 +39,11 @@ class TestGlobalNamespace(unittest.TestC
++ self.assertTrue(e[3])
++
++ # Unknown uppercase keys should be rejected.
++- with self.assertRaises(KeyError) as ke:
+++ ke = self.assertRaises(KeyError).__enter__()
+++ if 1:
++ ns['FOO'] = True
++
+++ ke.__exit__(0, 0, 0)
++ e = ke.exception.args
++ self.assertEqual(e[0], 'global_ns')
++ self.assertEqual(e[1], 'set_unknown')
++@@ -58,9 +62,11 @@ class TestGlobalNamespace(unittest.TestC
++ ns = GlobalNamespace(allowed_variables=VARIABLES)
++
++ # Setting to a non-allowed type should not work.
++- with self.assertRaises(ValueError) as ve:
+++ ve = self.assertRaises(ValueError).__enter__()
+++ if 1:
++ ns['DIRS'] = True
++
+++ ve.__exit__(0, 0, 0)
++ e = ve.exception.args
++ self.assertEqual(e[0], 'global_ns')
++ self.assertEqual(e[1], 'set_type')
++@@ -71,28 +77,38 @@ class TestGlobalNamespace(unittest.TestC
++ def test_allow_all_writes(self):
++ ns = GlobalNamespace(allowed_variables=VARIABLES)
++
++- with ns.allow_all_writes() as d:
+++ d = ns.allow_all_writes().__enter__()
+++ if 1:
++ d['foo'] = True
++ self.assertTrue(d['foo'])
++
++- with self.assertRaises(KeyError) as ke:
+++ d.__exit__(0, 0, 0)
+++ ke = self.assertRaises(KeyError).__enter__()
+++ if 1:
++ ns['bar'] = False
++
+++ ke.__exit__(0, 0, 0)
++ self.assertEqual(ke.exception.args[1], 'set_unknown')
++
++ ns['DIRS'] = []
++- with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
+++ ke = self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden').__enter__()
+++ if 1:
++ ns['DIRS'] = []
++
++- with ns.allow_all_writes() as d:
+++ ke.__exit__(0, 0, 0)
+++ d = ns.allow_all_writes().__enter__()
+++ if 1:
++ d['DIST_SUBDIR'] = 'foo'
++
+++ d.__exit__(0, 0, 0)
++ self.assertEqual(ns['DIST_SUBDIR'], 'foo')
++ ns['DIST_SUBDIR'] = 'bar'
++ self.assertEqual(ns['DIST_SUBDIR'], 'bar')
++- with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
+++ ke = self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden').__enter__()
+++ if 1:
++ ns['DIST_SUBDIR'] = 'baz'
++
+++ ke.__exit__(0, 0, 0)
++ self.assertTrue(d['foo'])
++
++ def test_key_checking(self):
++@@ -124,9 +140,11 @@ class TestLocalNamespace(unittest.TestCa
++ self.assertEqual(l['DIRS'], g['DIRS'])
++
++ # Reads to missing UPPERCASE vars should result in KeyError.
++- with self.assertRaises(KeyError) as ke:
+++ ke = self.assertRaises(KeyError).__enter__()
+++ if 1:
++ v = l['FOO']
++
+++ ke.__exit__(0, 0, 0)
++ e = ke.exception
++ self.assertEqual(e.args[0], 'global_ns')
++ self.assertEqual(e.args[1], 'get_unknown')
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py 2014-10-24 11:41:35.496880070 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import sys
++@@ -85,9 +85,11 @@ class TestBuildReader(unittest.TestCase)
++ # add_tier_dir() should fail when not in the top directory.
++ reader = self.reader('traversal-tier-fails-in-subdir')
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_relative_dirs(self):
++ # Ensure relative directories are traversed.
++ reader = self.reader('traversal-relative-dirs')
++@@ -106,15 +108,19 @@ class TestBuildReader(unittest.TestCase)
++ # References to directories outside the topsrcdir should fail.
++ reader = self.reader('traversal-outside-topsrcdir')
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_error_basic(self):
++ reader = self.reader('reader-error-basic')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertEqual(e.actual_file, self.file_path('reader-error-basic',
++ 'moz.build'))
++@@ -124,9 +130,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_included_from(self):
++ reader = self.reader('reader-error-included-from')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertEqual(e.actual_file,
++ self.file_path('reader-error-included-from', 'child.build'))
++@@ -138,9 +146,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_syntax_error(self):
++ reader = self.reader('reader-error-syntax')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('Python syntax error on line 5', str(e))
++ self.assertIn(' foo =', str(e))
++@@ -149,9 +159,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_read_unknown_global(self):
++ reader = self.reader('reader-error-read-unknown-global')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The error was triggered on line 5', str(e))
++ self.assertIn('The underlying problem is an attempt to read', str(e))
++@@ -160,9 +172,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_write_unknown_global(self):
++ reader = self.reader('reader-error-write-unknown-global')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The error was triggered on line 7', str(e))
++ self.assertIn('The underlying problem is an attempt to write', str(e))
++@@ -171,9 +185,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_write_bad_value(self):
++ reader = self.reader('reader-error-write-bad-value')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The error was triggered on line 5', str(e))
++ self.assertIn('is an attempt to write an illegal value to a special',
++@@ -190,9 +206,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_illegal_path(self):
++ reader = self.reader('reader-error-outside-topsrcdir')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The underlying problem is an illegal file access',
++ str(e))
++@@ -200,18 +218,22 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_missing_include_path(self):
++ reader = self.reader('reader-error-missing-include')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('we referenced a path that does not exist', str(e))
++
++ def test_error_script_error(self):
++ reader = self.reader('reader-error-script-error')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The error appears to be the fault of the script',
++ str(e))
++@@ -220,18 +242,22 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_bad_dir(self):
++ reader = self.reader('reader-error-bad-dir')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('we referenced a path that does not exist', str(e))
++
++ def test_error_repeated_dir(self):
++ reader = self.reader('reader-error-repeated-dir')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('Directory (foo) registered multiple times in DIRS',
++ str(e))
++@@ -239,9 +265,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_error_func(self):
++ reader = self.reader('reader-error-error-func')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('A moz.build file called the error() function.', str(e))
++ self.assertIn(' Some error.', str(e))
++@@ -249,9 +277,11 @@ class TestBuildReader(unittest.TestCase)
++ def test_error_traversal_tools(self):
++ reader = self.reader('reader-error-traversal-tools')
++
++- with self.assertRaises(BuildReaderError) as bre:
+++ bre = self.assertRaises(BuildReaderError).__enter__()
+++ if 1:
++ list(reader.read_topsrcdir())
++
+++ bre.__exit__(0, 0, 0)
++ e = bre.exception
++ self.assertIn('The DIRS variable is not allowed in such directories.', str(e))
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py 2014-10-24 11:41:35.496880070 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import shutil
++@@ -95,9 +95,11 @@ class TestSandbox(unittest.TestCase):
++ self.assertIsNone(sandbox['CONFIG']['MISSING'])
++
++ # Should shouldn't be allowed to assign to the config.
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ sandbox['CONFIG']['FOO'] = ''
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_dict_interface(self):
++ sandbox = self.sandbox()
++ config = sandbox.config
++@@ -127,9 +129,11 @@ class TestSandbox(unittest.TestCase):
++ def test_exec_compile_error(self):
++ sandbox = self.sandbox()
++
++- with self.assertRaises(SandboxExecutionError) as se:
+++ se = self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_source('2f23;k;asfj', 'foo.py')
++
+++ se.__exit__(0, 0, 0)
++ self.assertEqual(se.exception.file_stack, ['foo.py'])
++ self.assertIsInstance(se.exception.exc_value, SyntaxError)
++ self.assertEqual(sandbox.main_path, 'foo.py')
++@@ -137,9 +141,11 @@ class TestSandbox(unittest.TestCase):
++ def test_exec_import_denied(self):
++ sandbox = self.sandbox()
++
++- with self.assertRaises(SandboxExecutionError) as se:
+++ se = self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_source('import sys', 'import.py')
++
+++ se.__exit__(0, 0, 0)
++ self.assertIsInstance(se.exception, SandboxExecutionError)
++ self.assertEqual(se.exception.exc_type, ImportError)
++
++@@ -154,9 +160,11 @@ class TestSandbox(unittest.TestCase):
++ def test_exec_source_illegal_key_set(self):
++ sandbox = self.sandbox()
++
++- with self.assertRaises(SandboxExecutionError) as se:
+++ se = self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_source('ILLEGAL = True', 'foo.py')
++
+++ se.__exit__(0, 0, 0)
++ e = se.exception
++ self.assertIsInstance(e.exc_value, KeyError)
++
++@@ -216,9 +224,11 @@ add_tier_dir('t1', 'bat', static=True)
++
++ sandbox.exec_source('add_tier_dir("t1", "foo")', 'foo.py')
++
++- with self.assertRaises(SandboxExecutionError):
+++ self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_source('add_tier_dir("t1", "foo")', 'foo.py')
++
+++ self.assertRaises(SandboxExecutionError).__exit__(0, 0, 0)
++ def test_include_basic(self):
++ sandbox = self.sandbox(data_path='include-basic')
++
++@@ -232,9 +242,11 @@ add_tier_dir('t1', 'bat', static=True)
++ def test_include_outside_topsrcdir(self):
++ sandbox = self.sandbox(data_path='include-outside-topsrcdir')
++
++- with self.assertRaises(SandboxLoadError) as se:
+++ se = self.assertRaises(SandboxLoadError).__enter__()
+++ if 1:
++ sandbox.exec_file('relative.build')
++
+++ se.__exit__(0, 0, 0)
++ expected = mozpath.join(test_data_path, 'moz.build')
++ self.assertEqual(se.exception.illegal_path, expected)
++
++@@ -242,9 +254,11 @@ add_tier_dir('t1', 'bat', static=True)
++ # Ensure the path stack is reported properly in exceptions.
++ sandbox = self.sandbox(data_path='include-file-stack')
++
++- with self.assertRaises(SandboxExecutionError) as se:
+++ se = self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_file('moz.build')
++
+++ se.__exit__(0, 0, 0)
++ e = se.exception
++ self.assertIsInstance(e.exc_value, KeyError)
++
++@@ -261,9 +275,11 @@ add_tier_dir('t1', 'bat', static=True)
++ def test_include_missing(self):
++ sandbox = self.sandbox(data_path='include-missing')
++
++- with self.assertRaises(SandboxLoadError) as sle:
+++ sle = self.assertRaises(SandboxLoadError).__enter__()
+++ if 1:
++ sandbox.exec_file('moz.build')
++
+++ sle.__exit__(0, 0, 0)
++ self.assertIsNotNone(sle.exception.read_error)
++
++ def test_include_relative_from_child_dir(self):
++@@ -288,9 +304,11 @@ add_tier_dir('t1', 'bat', static=True)
++ def test_error(self):
++ sandbox = self.sandbox()
++
++- with self.assertRaises(SandboxCalledError) as sce:
+++ sce = self.assertRaises(SandboxCalledError).__enter__()
+++ if 1:
++ sandbox.exec_source('error("This is an error.")', 'test.py')
++
+++ sce.__exit__(0, 0, 0)
++ e = sce.exception
++ self.assertEqual(e.message, 'This is an error.')
++
++@@ -315,9 +333,11 @@ add_tier_dir('t1', 'bat', static=True)
++ def test_invalid_exports_set_base(self):
++ sandbox = self.sandbox()
++
++- with self.assertRaises(SandboxExecutionError) as se:
+++ se = self.assertRaises(SandboxExecutionError).__enter__()
+++ if 1:
++ sandbox.exec_source('EXPORTS = "foo.h"', 'foo.py')
++
+++ se.__exit__(0, 0, 0)
++ self.assertEqual(se.exception.exc_type, ValueError)
++
++ if __name__ == '__main__':
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/testing.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/testing.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/testing.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/testing.py 2014-10-24 11:41:35.496880070 -0600
++@@ -2,15 +2,15 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import json
++ import os
++
++ import mozpack.path as mozpath
++
++-from .base import MozbuildObject
++-from .util import DefaultOnReadDict
+++from base import MozbuildObject
+++from util import DefaultOnReadDict
++
++
++ def rewrite_test_base(test, new_base, honor_install_to_subdir=False):
++@@ -49,7 +49,8 @@ class TestMetadata(object):
++ self._test_dirs = set()
++
++ if filename:
++- with open(filename, 'rt') as fh:
+++ fh = open(filename, 'rt')
+++ if 1:
++ d = json.load(fh)
++
++ for path, tests in d.items():
++@@ -60,6 +61,7 @@ class TestMetadata(object):
++ flavor = metadata.get('flavor')
++ self._tests_by_flavor[flavor].add(path)
++
+++ fh.close()
++ def tests_with_flavor(self, flavor):
++ """Obtain all tests having the specified flavor.
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_base.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_base.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_base.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_base.py 2014-10-24 11:41:35.497880066 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import json
++ import os
++@@ -49,7 +49,8 @@ class TestMozbuildObject(unittest.TestCa
++ def test_objdir_config_guess(self):
++ base = self.get_base()
++
++- with NamedTemporaryFile() as mozconfig:
+++ mozconfig = NamedTemporaryFile().__enter__()
+++ if 1:
++ os.environ[b'MOZCONFIG'] = mozconfig.name
++
++ self.assertIsNotNone(base.topobjdir)
++@@ -58,11 +59,13 @@ class TestMozbuildObject(unittest.TestCa
++ self.assertTrue(os.path.isabs(base.topobjdir))
++ self.assertTrue(base.topobjdir.startswith(topsrcdir))
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_objdir_trailing_slash(self):
++ """Trailing slashes in topobjdir should be removed."""
++ base = self.get_base()
++
++- with NamedTemporaryFile() as mozconfig:
+++ mozconfig = NamedTemporaryFile().__enter__()
+++ if 1:
++ mozconfig.write('mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/')
++ mozconfig.flush()
++ os.environ[b'MOZCONFIG'] = mozconfig.name
++@@ -71,6 +74,7 @@ class TestMozbuildObject(unittest.TestCa
++ 'foo'))
++ self.assertTrue(base.topobjdir.endswith('foo'))
++
+++ mozconfig.__exit__(0, 0, 0)
++ @unittest.skip('Failing on buildbot.')
++ def test_objdir_config_status(self):
++ """Ensure @CONFIG_GUESS@ is handled when loading mozconfig."""
++@@ -82,8 +86,10 @@ class TestMozbuildObject(unittest.TestCa
++ d = os.path.realpath(tempfile.mkdtemp())
++ try:
++ mozconfig = os.path.join(d, 'mozconfig')
++- with open(mozconfig, 'wt') as fh:
+++ fh = open(mozconfig, 'wt')
+++ if 1:
++ fh.write('mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/@CONFIG_GUESS@')
+++ fh.__exit__(0, 0, 0)
++ print('Wrote mozconfig %s' % mozconfig)
++
++ topobjdir = os.path.join(d, 'foo', guess)
++@@ -96,12 +102,14 @@ class TestMozbuildObject(unittest.TestCa
++ 'config.guess',), guess_path)
++
++ mozinfo = os.path.join(topobjdir, 'mozinfo.json')
++- with open(mozinfo, 'wt') as fh:
+++ fh = open(mozinfo, 'wt')
+++ if 1:
++ json.dump(dict(
++ topsrcdir=d,
++ mozconfig=mozconfig,
++ ), fh)
++
+++ fh.__exit__(0, 0, 0)
++ os.environ[b'MOZCONFIG'] = mozconfig
++ os.chdir(topobjdir)
++
++@@ -117,19 +125,23 @@ class TestMozbuildObject(unittest.TestCa
++ d = os.path.realpath(tempfile.mkdtemp())
++ try:
++ mozconfig = os.path.join(d, 'mozconfig')
++- with open(mozconfig, 'wt') as fh:
+++ fh = open(mozconfig, 'wt').__enter__()
+++ if 1:
++ fh.write('mk_add_options MOZ_OBJDIR=./objdir')
++
+++ fh.__exit__(0, 0, 0)
++ topobjdir = os.path.join(d, 'objdir')
++ os.mkdir(topobjdir)
++
++ mozinfo = os.path.join(topobjdir, 'mozinfo.json')
++- with open(mozinfo, 'wt') as fh:
+++ fh = open(mozinfo, 'wt').__enter__()
+++ if 1:
++ json.dump(dict(
++ topsrcdir=d,
++ mozconfig=mozconfig,
++ ), fh)
++
+++ fh.__exit__(0, 0, 0)
++ os.environ[b'MOZCONFIG'] = mozconfig
++ child = os.path.join(topobjdir, 'foo', 'bar')
++ os.makedirs(child)
++@@ -154,16 +166,20 @@ class TestMozbuildObject(unittest.TestCa
++ os.symlink(topobjdir_real, topobjdir_link)
++
++ mozconfig = os.path.join(d, 'mozconfig')
++- with open(mozconfig, 'wt') as fh:
+++ fh = open(mozconfig, 'wt').__enter__()
+++ if 1:
++ fh.write('mk_add_options MOZ_OBJDIR=%s' % topobjdir_link)
++
+++ fh.__exit__(0, 0, 0)
++ mozinfo = os.path.join(topobjdir_real, 'mozinfo.json')
++- with open(mozinfo, 'wt') as fh:
+++ fh = open(mozinfo, 'wt').__enter__()
+++ if 1:
++ json.dump(dict(
++ topsrcdir=d,
++ mozconfig=mozconfig,
++ ), fh)
++
+++ fh.__exit__(0, 0, 0)
++ os.chdir(topobjdir_link)
++ obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
++ self.assertEqual(obj.topobjdir, topobjdir_real)
++@@ -189,11 +205,13 @@ class TestMozbuildObject(unittest.TestCa
++ os.makedirs(topsrcdir)
++
++ mozinfo = os.path.join(topobjdir, 'mozinfo.json')
++- with open(mozinfo, 'wt') as fh:
+++ fh = open(mozinfo, 'wt').__enter__()
+++ if 1:
++ json.dump(dict(
++ topsrcdir=topsrcdir,
++ ), fh)
++
+++ fh.close()
++ os.chdir(topobjdir)
++
++ class MockMachContext(object):
++@@ -222,14 +240,18 @@ class TestMozbuildObject(unittest.TestCa
++ # The easiest way to do this is to create a mozinfo.json with data
++ # that will never happen.
++ mozinfo = os.path.join(d, 'mozinfo.json')
++- with open(mozinfo, 'wt') as fh:
+++ fh = open(mozinfo, 'wt').__enter__()
+++ if 1:
++ json.dump({'topsrcdir': d}, fh)
++
+++ fh.close()
++ os.chdir(d)
++
++- with self.assertRaises(BadEnvironmentException):
+++ self.assertRaises(BadEnvironmentException).__enter__()
+++ if 1:
++ MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
++
+++ self.assertRaises(BadEnvironmentException).__exit__(0, 0, 0)
++ finally:
++ shutil.rmtree(d)
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_containers.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_containers.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_containers.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_containers.py 2014-10-24 11:41:35.497880066 -0600
++@@ -21,12 +21,16 @@ class TestReadOnlyDict(unittest.TestCase
++ self.assertEqual(original, test)
++ self.assertEqual(test['foo'], 1)
++
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ value = test['missing']
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ test['baz'] = True
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ class TestDefaultOnReadDict(unittest.TestCase):
++ def test_no_defaults(self):
++ original = {'foo': 1, 'bar': 2}
++@@ -34,9 +38,11 @@ class TestDefaultOnReadDict(unittest.Tes
++ test = DefaultOnReadDict(original)
++ self.assertEqual(original, test)
++
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ value = test['missing']
++
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
++ test['foo'] = 5
++ self.assertEqual(test['foo'], 5)
++
++@@ -48,9 +54,11 @@ class TestDefaultOnReadDict(unittest.Tes
++ self.assertEqual(original, test)
++ self.assertEqual(test['baz'], 3)
++
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ value = test['missing']
++
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
++ test['baz'] = 4
++ self.assertEqual(test['baz'], 4)
++
++@@ -85,15 +93,19 @@ class TestReadOnlyDefaultDict(unittest.T
++
++ self.assertEqual(test['foo'], 1)
++
++- with self.assertRaises(KeyError):
+++ self.assertRaises(KeyError).__enter__()
+++ if 1:
++ value = test['missing']
++
+++ self.assertRaises(KeyError).__exit__(0, 0, 0)
++ def test_assignment(self):
++ test = ReadOnlyDefaultDict({})
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ test['foo'] = True
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_defaults(self):
++ test = ReadOnlyDefaultDict({}, defaults={'foo': 1})
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py 2014-10-24 11:41:35.497880066 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import unittest
++@@ -54,9 +54,11 @@ class TestMozconfigLoader(unittest.TestC
++
++ os.environ[b'MOZ_MYCONFIG'] = '/foo'
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ self.get_loader().find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertTrue(e.exception.message.startswith('The MOZ_MYCONFIG'))
++
++ def test_find_multiple_configs(self):
++@@ -70,14 +72,18 @@ class TestMozconfigLoader(unittest.TestC
++ loader = MozconfigLoader(srcdir)
++ for d in dirs:
++ path = os.path.join(d, relative_mozconfig)
++- with open(path, 'wb') as f:
+++ f = open(path, 'wb')
+++ if 1:
++ f.write(path)
++
+++ f.close()
++ orig_dir = os.getcwd()
++ try:
++ os.chdir(curdir)
++- with self.assertRaises(MozconfigFindException) as e:
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ loader.find_mozconfig()
+++ e.__exit__(0, 0, 0)
++ finally:
++ os.chdir(orig_dir)
++
++@@ -98,9 +104,11 @@ class TestMozconfigLoader(unittest.TestC
++
++ loader = MozconfigLoader(srcdir)
++ path = os.path.join(srcdir, relative_mozconfig)
++- with open(path, 'w'):
+++ open(path, 'w').__enter__()
+++ if 1:
++ pass
++
+++ open(path, 'w').__exit__(0, 0, 0)
++ orig_dir = os.getcwd()
++ try:
++ os.chdir(curdir)
++@@ -122,8 +130,10 @@ class TestMozconfigLoader(unittest.TestC
++ orig_dir = os.getcwd()
++ try:
++ os.chdir(curdir)
++- with self.assertRaises(MozconfigFindException) as e:
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ loader.find_mozconfig()
+++ e.__exit__(0, 0, 0)
++ finally:
++ os.chdir(orig_dir)
++
++@@ -142,9 +152,11 @@ class TestMozconfigLoader(unittest.TestC
++ loader = MozconfigLoader(srcdir)
++
++ path = os.path.join(srcdir, relative_mozconfig)
++- with open(path, 'w'):
+++ open(path, 'w').__enter__()
+++ if 1:
++ pass
++
+++ open(path, 'w').__exit__(0, 0, 0)
++ orig_dir = os.getcwd()
++ try:
++ os.chdir(curdir)
++@@ -157,9 +169,11 @@ class TestMozconfigLoader(unittest.TestC
++ """Ensure a missing absolute path is detected."""
++ os.environ[b'MOZCONFIG'] = '/foo/bar/does/not/exist'
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ self.get_loader().find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertIn('path that does not exist', e.exception.message)
++ self.assertTrue(e.exception.message.endswith('/foo/bar/does/not/exist'))
++
++@@ -168,9 +182,11 @@ class TestMozconfigLoader(unittest.TestC
++
++ os.environ[b'MOZCONFIG'] = gettempdir()
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ self.get_loader().find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertIn('refers to a non-file', e.exception.message)
++ self.assertTrue(e.exception.message.endswith(gettempdir()))
++
++@@ -180,9 +196,11 @@ class TestMozconfigLoader(unittest.TestC
++ d = self.get_temp_dir()
++ path = os.path.join(d, p)
++
++- with open(path, 'w'):
+++ open(path, 'w').__enter__()
+++ if 1:
++ pass
++
+++ open(path, 'w').__exit__(0, 0, 0)
++ self.assertEqual(MozconfigLoader(d).find_mozconfig(), path)
++
++ def test_find_multiple_defaults(self):
++@@ -191,12 +209,16 @@ class TestMozconfigLoader(unittest.TestC
++
++ d = self.get_temp_dir()
++ for p in MozconfigLoader.DEFAULT_TOPSRCDIR_PATHS:
++- with open(os.path.join(d, p), 'w'):
+++ open(os.path.join(d, p), 'w').__enter__()
+++ if 1:
++ pass
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ open(os.path.join(d, p), 'w').__exit__(0, 0, 0)
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ MozconfigLoader(d).find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertIn('Multiple default mozconfig files present',
++ e.exception.message)
++
++@@ -204,12 +226,16 @@ class TestMozconfigLoader(unittest.TestC
++ """Ensure we error when deprecated path locations are present."""
++ for p in MozconfigLoader.DEPRECATED_TOPSRCDIR_PATHS:
++ d = self.get_temp_dir()
++- with open(os.path.join(d, p), 'w'):
+++ open(os.path.join(d, p), 'w').__enter__()
+++ if 1:
++ pass
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ open(os.path.join(d, p), 'w').__exit__(0, 0, 0)
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ MozconfigLoader(d).find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertIn('This implicit location is no longer',
++ e.exception.message)
++ self.assertIn(d, e.exception.message)
++@@ -222,12 +248,16 @@ class TestMozconfigLoader(unittest.TestC
++ os.environ[b'HOME'] = home
++ path = os.path.join(home, p)
++
++- with open(path, 'w'):
+++ open(path, 'w').__enter__()
+++ if 1:
++ pass
++
++- with self.assertRaises(MozconfigFindException) as e:
+++ open(path, 'w').__exit__(0, 0, 0)
+++ e = self.assertRaises(MozconfigFindException).__enter__()
+++ if 1:
++ self.get_loader().find_mozconfig()
++
+++ e.__exit__(0, 0, 0)
++ self.assertIn('This implicit location is no longer',
++ e.exception.message)
++ self.assertIn(path, e.exception.message)
++@@ -246,7 +276,8 @@ class TestMozconfigLoader(unittest.TestC
++ })
++
++ def test_read_empty_mozconfig(self):
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ result = self.get_loader().read_mozconfig(mozconfig.name)
++
++ self.assertEqual(result['path'], mozconfig.name)
++@@ -260,9 +291,11 @@ class TestMozconfigLoader(unittest.TestC
++
++ self.assertGreater(len(result['env']['unmodified']), 0)
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_capture_ac_options(self):
++ """Ensures ac_add_options calls are captured."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('ac_add_options --enable-debug\n')
++ mozconfig.write('ac_add_options --disable-tests --enable-foo\n')
++ mozconfig.write('ac_add_options --foo="bar baz"\n')
++@@ -273,9 +306,11 @@ class TestMozconfigLoader(unittest.TestC
++ '--enable-debug', '--disable-tests', '--enable-foo',
++ '--foo=bar baz'])
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_ac_options_substitution(self):
++ """Ensure ac_add_options values are substituted."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('ac_add_options --foo=@TOPSRCDIR@\n')
++ mozconfig.flush()
++
++@@ -284,8 +319,10 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['configure_args'], [
++ '--foo=%s' % loader.topsrcdir])
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_ac_app_options(self):
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('ac_add_options --foo=@TOPSRCDIR@\n')
++ mozconfig.write('ac_add_app_options app1 --bar=@TOPSRCDIR@\n')
++ mozconfig.write('ac_add_app_options app2 --bar=x\n')
++@@ -302,9 +339,11 @@ class TestMozconfigLoader(unittest.TestC
++ '--foo=%s' % loader.topsrcdir,
++ '--bar=x'])
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_capture_mk_options(self):
++ """Ensures mk_add_options calls are captured."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('mk_add_options MOZ_OBJDIR=/foo/bar\n')
++ mozconfig.write('mk_add_options MOZ_MAKE_FLAGS=-j8\n')
++ mozconfig.write('mk_add_options FOO="BAR BAZ"\n')
++@@ -316,9 +355,11 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['make_flags'], '-j8')
++ self.assertEqual(result['make_extra'], ['FOO=BAR BAZ', 'BIZ=1'])
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_moz_objdir_substitution(self):
++ """Ensure @TOPSRCDIR@ substitution is recognized in MOZ_OBJDIR."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/some-objdir')
++ mozconfig.flush()
++
++@@ -328,9 +369,11 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['topobjdir'], '%s/some-objdir' %
++ loader.topsrcdir)
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_new_variables(self):
++ """New variables declared in mozconfig file are detected."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('CC=/usr/local/bin/clang\n')
++ mozconfig.write('CXX=/usr/local/bin/clang++\n')
++ mozconfig.flush()
++@@ -341,9 +384,11 @@ class TestMozconfigLoader(unittest.TestC
++ 'CC': '/usr/local/bin/clang',
++ 'CXX': '/usr/local/bin/clang++'})
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_exported_variables(self):
++ """Exported variables are caught as new variables."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('export MY_EXPORTED=woot\n')
++ mozconfig.flush()
++
++@@ -352,11 +397,13 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['env']['added'], {
++ 'MY_EXPORTED': 'woot'})
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_modify_variables(self):
++ """Variables modified by mozconfig are detected."""
++- os.environ[b'CC'] = b'/usr/bin/gcc'
+++ os.environ[b'CC'] = '/usr/bin/gcc'
++
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('CC=/usr/local/bin/clang\n')
++ mozconfig.flush()
++
++@@ -366,11 +413,13 @@ class TestMozconfigLoader(unittest.TestC
++ 'CC': ('/usr/bin/gcc', '/usr/local/bin/clang')
++ })
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_removed_variables(self):
++ """Variables unset by the mozconfig are detected."""
++- os.environ[b'CC'] = b'/usr/bin/clang'
+++ os.environ[b'CC'] = '/usr/bin/clang'
++
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('unset CC\n')
++ mozconfig.flush()
++
++@@ -379,9 +428,11 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['env']['removed'], {
++ 'CC': '/usr/bin/clang'})
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_multiline_variables(self):
++ """Ensure multi-line variables are captured properly."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('multi="foo\nbar"\n')
++ mozconfig.write('single=1\n')
++ mozconfig.flush()
++@@ -393,9 +444,11 @@ class TestMozconfigLoader(unittest.TestC
++ 'single': '1'
++ })
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_topsrcdir_defined(self):
++ """Ensure $topsrcdir references work as expected."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('TEST=$topsrcdir')
++ mozconfig.flush()
++
++@@ -405,9 +458,11 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEqual(result['env']['added']['TEST'],
++ loader.topsrcdir.replace(os.sep, '/'))
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_empty_variable_value(self):
++ """Ensure empty variable values are parsed properly."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('EMPTY=\n')
++ mozconfig.flush()
++
++@@ -416,16 +471,20 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertIn('EMPTY', result['env']['added'])
++ self.assertEqual(result['env']['added']['EMPTY'], '')
++
+++ mozconfig.__exit__(0, 0, 0)
++ def test_read_load_exception(self):
++ """Ensure non-0 exit codes in mozconfigs are handled properly."""
++- with NamedTemporaryFile(mode='w') as mozconfig:
+++ mozconfig = NamedTemporaryFile(mode='w').__enter__()
+++ if 1:
++ mozconfig.write('echo "hello world"\n')
++ mozconfig.write('exit 1\n')
++ mozconfig.flush()
++
++- with self.assertRaises(MozconfigLoadException) as e:
+++ e = self.assertRaises(MozconfigLoadException).__enter__()
+++ if 1:
++ self.get_loader().read_mozconfig(mozconfig.name)
++
+++ e.__exit__(0, 0, 0)
++ self.assertTrue(e.exception.message.startswith(
++ 'Evaluation of your mozconfig exited with an error'))
++ self.assertEquals(e.exception.path,
++@@ -433,5 +492,6 @@ class TestMozconfigLoader(unittest.TestC
++ self.assertEquals(e.exception.output, ['hello world'])
++
++
+++ mozconfig.__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py 2014-10-24 11:41:35.498880062 -0600
++@@ -34,15 +34,21 @@ class TestBuildDict(unittest.TestCase, B
++ Test that missing required values raises.
++ """
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ build_dict(self._config(substs=dict(OS_TARGET='foo')))
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ build_dict(self._config(substs=dict(TARGET_CPU='foo')))
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ build_dict(self._config(substs=dict(MOZ_WIDGET_TOOLKIT='foo')))
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ def test_win(self):
++ d = build_dict(self._config(dict(
++ OS_TARGET='WINNT',
++@@ -242,11 +248,13 @@ class TestWriteMozinfo(unittest.TestCase
++ ))
++ tempdir = tempfile.tempdir
++ c.topsrcdir = tempdir
++- with NamedTemporaryFile(dir=os.path.normpath(c.topsrcdir)) as mozconfig:
+++ mozconfig = NamedTemporaryFile(dir=os.path.normpath(c.topsrcdir)).__enter__()
+++ if 1:
++ mozconfig.write('unused contents')
++ mozconfig.flush()
++ write_mozinfo(self.f, c, {'MOZCONFIG': mozconfig.name})
++- with open(self.f) as f:
+++ f = open(self.f)
+++ if 1:
++ d = json.load(f)
++ self.assertEqual('win', d['os'])
++ self.assertEqual('x86', d['processor'])
++@@ -255,6 +263,8 @@ class TestWriteMozinfo(unittest.TestCase
++ self.assertEqual(mozconfig.name, d['mozconfig'])
++ self.assertEqual(32, d['bits'])
++
+++ f.close()
+++ mozconfig.__exit__(0, 0, 0)
++ def test_fileobj(self):
++ """
++ Test that writing to a file-like object produces correct output.
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py 2014-10-24 11:41:35.498880062 -0600
++@@ -28,10 +28,12 @@ class TestPreprocessor(unittest.TestCase
++ content = '%s' % '\n'.join(content_lines)
++ expected = '%s'.rstrip() % '\n'.join(expected_lines)
++
++- with MockedOpen({'dummy': content}):
+++ MockedOpen({'dummy': content}).__enter__()
+++ if 1:
++ self.pp.do_include('dummy')
++ self.assertEqual(self.pp.out.getvalue().rstrip('\n'), expected)
++
+++ MockedOpen({'dummy': content}).__exit__(0, 0, 0)
++ def do_include_pass(self, content_lines):
++ self.do_include_compare(content_lines, ['PASS'])
++
++@@ -267,18 +269,23 @@ class TestPreprocessor(unittest.TestCase
++ ])
++
++ def test_error(self):
++- with MockedOpen({'f': '#error spit this message out\n'}):
++- with self.assertRaises(Preprocessor.Error) as e:
+++ MockedOpen({'f': '#error spit this message out\n'}).__enter__()
+++ if 1:
+++ e = self.assertRaises(Preprocessor.Error).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(e.args[0][-1], 'spit this message out')
++
+++ e.__exit__(0, 0, 0)
+++ MockedOpen({'f': '#error spit this message out\n'}).__exit__(0, 0, 0)
++ def test_javascript_line(self):
++ # The preprocessor is reading the filename from somewhere not caught
++ # by MockedOpen.
++ tmpdir = mkdtemp()
++ try:
++ full = os.path.join(tmpdir, 'javascript_line.js.in')
++- with open(full, 'w') as fh:
+++ fh = open(full, 'w')
+++ if 1:
++ fh.write('\n'.join([
++ '// Line 1',
++ '#if 0',
++@@ -296,6 +303,7 @@ class TestPreprocessor(unittest.TestCase
++ '',
++ ]))
++
+++ fh.close()
++ self.pp.do_include(full)
++ out = '\n'.join([
++ '// Line 1',
++@@ -441,11 +449,13 @@ class TestPreprocessor(unittest.TestCase
++ ])
++
++ def test_lineEndings(self):
++- with MockedOpen({'f': 'first\n#literal second\n'}):
+++ MockedOpen({'f': 'first\n#literal second\n'}).__enter__()
+++ if 1:
++ self.pp.setLineEndings('cr')
++ self.pp.do_include('f')
++ self.assertEqual(self.pp.out.getvalue(), "first\rsecond\r")
++
+++ MockedOpen({'f': 'first\n#literal second\n'}).__exit__(0, 0, 0)
++ def test_filterDefine(self):
++ self.do_include_pass([
++ '#filter substitution',
++@@ -532,11 +542,15 @@ class TestPreprocessor(unittest.TestCase
++ ])
++
++ def test_undefined_variable(self):
++- with MockedOpen({'f': '#filter substitution\n at foo@'}):
++- with self.assertRaises(Preprocessor.Error) as e:
+++ MockedOpen({'f': '#filter substitution\n at foo@'}).__enter__()
+++ if 1:
+++ e = self.assertRaises(Preprocessor.Error).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(e.key, 'UNDEFINED_VAR')
++
+++ e.__exit__(0, 0, 0)
+++ MockedOpen({'f': '#filter substitution\n at foo@'}).__exit__(0, 0, 0)
++ def test_include(self):
++ files = {
++ 'foo/test': '\n'.join([
++@@ -558,36 +572,50 @@ class TestPreprocessor(unittest.TestCase
++ ]),
++ }
++
++- with MockedOpen(files):
+++ MockedOpen(files).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\nbarfoobaz\n')
++
+++ MockedOpen(files).__exit__(0, 0, 0)
++ def test_include_missing_file(self):
++- with MockedOpen({'f': '#include foo\n'}):
++- with self.assertRaises(Preprocessor.Error) as e:
+++ MockedOpen({'f': '#include foo\n'}).__enter__()
+++ if 1:
+++ e = self.assertRaises(Preprocessor.Error).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(e.key, 'FILE_NOT_FOUND')
++
+++ e.__exit__(0, 0, 0)
+++ MockedOpen({'f': '#include foo\n'}).__exit__(0, 0, 0)
++ def test_include_undefined_variable(self):
++- with MockedOpen({'f': '#filter substitution\n#include @foo@\n'}):
++- with self.assertRaises(Preprocessor.Error) as e:
+++ MockedOpen({'f': '#filter substitution\n#include @foo@\n'}).__enter__()
+++ if 1:
+++ e = self.assertRaises(Preprocessor.Error).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(e.key, 'UNDEFINED_VAR')
++
+++ e.__exit__(0, 0, 0)
+++ MockedOpen({'f': '#filter substitution\n#include @foo@\n'}).__exit__(0, 0, 0)
++ def test_include_literal_at(self):
++ files = {
++ '@foo@': '#define foo foobarbaz\n',
++ 'f': '#include @foo@\n#filter substitution\n at foo@\n',
++ }
++
++- with MockedOpen(files):
+++ MockedOpen(files).__enter__()
+++ if 1:
++ self.pp.do_include('f')
++ self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')
++
+++ MockedOpen(files).__exit__(0, 0, 0)
++ def test_command_line_literal_at(self):
++- with MockedOpen({"@foo at .in": '@foo@\n'}):
+++ MockedOpen({"@foo at .in": '@foo@\n'}).__enter__()
+++ if 1:
++ self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo at .in'])
++ self.assertEqual(self.pp.out.getvalue(), 'foobarbaz\n')
++
+++ MockedOpen({"@foo at .in": '@foo@\n'}).__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_testing.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_testing.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_testing.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_testing.py 2014-10-24 11:41:35.498880062 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import shutil
++@@ -21,7 +21,7 @@ from mozbuild.testing import (
++ )
++
++
++-ALL_TESTS_JSON = b'''
+++ALL_TESTS_JSON = '''
++ {
++ "accessible/tests/mochitest/actions/test_anchors.html": [
++ {
++@@ -175,9 +175,11 @@ class TestTestResolver(Base):
++ topobjdir = tempfile.mkdtemp()
++ self._temp_dirs.append(topobjdir)
++
++- with open(os.path.join(topobjdir, 'all-tests.json'), 'wt') as fh:
+++ fh = open(os.path.join(topobjdir, 'all-tests.json'), 'wt')
+++ if 1:
++ fh.write(ALL_TESTS_JSON)
++
+++ fh.close()
++ o = MozbuildObject(self.FAKE_TOPSRCDIR, None, None, topobjdir=topobjdir)
++
++ return o._spawn(TestResolver)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_util.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_util.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_util.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/test/test_util.py 2014-10-24 11:41:35.499880057 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import hashlib
++ import os
++@@ -41,7 +41,7 @@ data_path = os.path.join(data_path, 'dat
++ class TestHashing(unittest.TestCase):
++ def test_hash_file_known_hash(self):
++ """Ensure a known hash value is recreated."""
++- data = b'The quick brown fox jumps over the lazy cog'
+++ data = 'The quick brown fox jumps over the lazy cog'
++ expected = 'de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3'
++
++ temp = NamedTemporaryFile()
++@@ -54,7 +54,7 @@ class TestHashing(unittest.TestCase):
++
++ def test_hash_file_large(self):
++ """Ensure that hash_file seems to work with a large file."""
++- data = b'x' * 1048576
+++ data = 'x' * 1048576
++
++ hasher = hashlib.sha1()
++ hasher.update(data)
++@@ -71,7 +71,8 @@ class TestHashing(unittest.TestCase):
++
++ class TestFileAvoidWrite(unittest.TestCase):
++ def test_file_avoid_write(self):
++- with MockedOpen({'file': 'content'}):
+++ MockedOpen({'file': 'content'}).__enter__()
+++ if 1:
++ # Overwriting an existing file replaces its content
++ faw = FileAvoidWrite('file')
++ faw.write('bazqux')
++@@ -84,12 +85,17 @@ class TestFileAvoidWrite(unittest.TestCa
++ self.assertEqual(faw.close(), (False, True))
++ self.assertEqual(open('file2').read(), 'content')
++
++- with MockedOpen({'file': 'content'}):
++- with FileAvoidWrite('file') as file:
+++ MockedOpen({'file': 'content'}).__exit__(0, 0, 0)
+++ MockedOpen({'file': 'content'}).__enter__()
+++ if 1:
+++ file = FileAvoidWrite('file').__enter__()
+++ if 1:
++ file.write('foobar')
++
+++ file.__exit__(0, 0, 0)
++ self.assertEqual(open('file', 'r').read(), 'foobar')
++
+++ MockedOpen({'file': 'content'}).__exit__(0, 0, 0)
++ class MyMockedOpen(MockedOpen):
++ '''MockedOpen extension to raise an exception if something
++ attempts to write in an opened file.
++@@ -99,7 +105,8 @@ class TestFileAvoidWrite(unittest.TestCa
++ raise Exception, 'Unexpected open with write mode'
++ return MockedOpen.__call__(self, name, mode)
++
++- with MyMockedOpen({'file': 'content'}):
+++ MyMockedOpen({'file': 'content'}).__enter__()
+++ if 1:
++ # Validate that MyMockedOpen works as intended
++ file = FileAvoidWrite('file')
++ file.write('foobar')
++@@ -111,19 +118,23 @@ class TestFileAvoidWrite(unittest.TestCa
++ faw.write('content')
++ self.assertEqual(faw.close(), (True, False))
++
+++ MyMockedOpen({'file': 'content'}).__exit__(0, 0, 0)
++ def test_diff_not_default(self):
++ """Diffs are not produced by default."""
++
++- with MockedOpen({'file': 'old'}):
+++ MockedOpen({'file': 'old'}).__enter__()
+++ if 1:
++ faw = FileAvoidWrite('file')
++ faw.write('dummy')
++ faw.close()
++ self.assertIsNone(faw.diff)
++
+++ MockedOpen({'file': 'old'}).__exit__(0, 0, 0)
++ def test_diff_update(self):
++ """Diffs are produced on file update."""
++
++- with MockedOpen({'file': 'old'}):
+++ MockedOpen({'file': 'old'}).__enter__()
+++ if 1:
++ faw = FileAvoidWrite('file', capture_diff=True)
++ faw.write('new')
++ faw.close()
++@@ -132,6 +143,7 @@ class TestFileAvoidWrite(unittest.TestCa
++ self.assertIn('-old', diff)
++ self.assertIn('+new', diff)
++
+++ MockedOpen({'file': 'old'}).__exit__(0, 0, 0)
++ def test_diff_create(self):
++ """Diffs are produced when files are created."""
++
++@@ -228,43 +240,55 @@ class TestHierarchicalStringList(unittes
++ self.assertEqual(self.EXPORTS.foo.bar.get_strings(), ["foobar.h"])
++
++ def test_invalid_exports_append(self):
++- with self.assertRaises(ValueError) as ve:
+++ ve = self.assertRaises(ValueError).__enter__()
+++ if 1:
++ self.EXPORTS += "foo.h"
+++ ve.__exit__(0, 0, 0)
++ self.assertEqual(str(ve.exception),
++ "Expected a list of strings, not <type '%s'>" % str_type)
++
++ def test_invalid_exports_set(self):
++- with self.assertRaises(ValueError) as ve:
+++ ve = self.assertRaises(ValueError).__enter__()
+++ if 1:
++ self.EXPORTS.foo = "foo.h"
++
+++ ve.__exit__(0, 0, 0)
++ self.assertEqual(str(ve.exception),
++ "Expected a list of strings, not <type '%s'>" % str_type)
++
++ def test_invalid_exports_append_base(self):
++- with self.assertRaises(ValueError) as ve:
+++ ve = self.assertRaises(ValueError).__enter__()
+++ if 1:
++ self.EXPORTS += "foo.h"
++
+++ ve.__exit__(0, 0, 0)
++ self.assertEqual(str(ve.exception),
++ "Expected a list of strings, not <type '%s'>" % str_type)
++
++ def test_invalid_exports_bool(self):
++- with self.assertRaises(ValueError) as ve:
+++ ve = self.assertRaises(ValueError).__enter__()
+++ if 1:
++ self.EXPORTS += [True]
++
+++ ve.__exit__(0, 0, 0)
++ self.assertEqual(str(ve.exception),
++ "Expected a list of strings, not an element of "
++ "<type 'bool'>")
++
++ def test_del_exports(self):
++- with self.assertRaises(MozbuildDeletionError) as mde:
+++ mde = self.assertRaises(MozbuildDeletionError).__enter__()
+++ if 1:
++ self.EXPORTS.foo += ['bar.h']
++ del self.EXPORTS.foo
++
+++ mde.__exit__(0, 0, 0)
++ def test_unsorted_appends(self):
++- with self.assertRaises(UnsortedError) as ee:
+++ ee = self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ self.EXPORTS += ['foo.h', 'bar.h']
++
++
+++ ee.__exit__(0, 0, 0)
++ class TestStrictOrderingOnAppendList(unittest.TestCase):
++ def test_init(self):
++ l = StrictOrderingOnAppendList()
++@@ -273,9 +297,11 @@ class TestStrictOrderingOnAppendList(uni
++ l = StrictOrderingOnAppendList(['a', 'b', 'c'])
++ self.assertEqual(len(l), 3)
++
++- with self.assertRaises(UnsortedError):
+++ self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ StrictOrderingOnAppendList(['c', 'b', 'a'])
++
+++ self.assertRaises(UnsortedError).__exit__(0, 0, 0)
++ self.assertEqual(len(l), 3)
++
++ def test_extend(self):
++@@ -284,9 +310,11 @@ class TestStrictOrderingOnAppendList(uni
++ self.assertEqual(len(l), 2)
++ self.assertIsInstance(l, StrictOrderingOnAppendList)
++
++- with self.assertRaises(UnsortedError):
+++ self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ l.extend(['d', 'c'])
++
+++ self.assertRaises(UnsortedError).__exit__(0, 0, 0)
++ self.assertEqual(len(l), 2)
++
++ def test_slicing(self):
++@@ -295,9 +323,11 @@ class TestStrictOrderingOnAppendList(uni
++ self.assertEqual(len(l), 2)
++ self.assertIsInstance(l, StrictOrderingOnAppendList)
++
++- with self.assertRaises(UnsortedError):
+++ self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ l[:] = ['b', 'a']
++
+++ self.assertRaises(UnsortedError).__exit__(0, 0, 0)
++ self.assertEqual(len(l), 2)
++
++ def test_add(self):
++@@ -307,9 +337,11 @@ class TestStrictOrderingOnAppendList(uni
++ self.assertEqual(len(l2), 2)
++ self.assertIsInstance(l2, StrictOrderingOnAppendList)
++
++- with self.assertRaises(UnsortedError):
+++ self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ l2 = l + ['b', 'a']
++
+++ self.assertRaises(UnsortedError).__exit__(0, 0, 0)
++ self.assertEqual(len(l), 0)
++
++ def test_iadd(self):
++@@ -318,9 +350,11 @@ class TestStrictOrderingOnAppendList(uni
++ self.assertEqual(len(l), 2)
++ self.assertIsInstance(l, StrictOrderingOnAppendList)
++
++- with self.assertRaises(UnsortedError):
+++ self.assertRaises(UnsortedError).__enter__()
+++ if 1:
++ l += ['b', 'a']
++
+++ self.assertRaises(UnsortedError).__exit__(0, 0, 0)
++ self.assertEqual(len(l), 2)
++
++
++@@ -334,19 +368,25 @@ class TestStrictOrderingOnAppendListWith
++ l = cls()
++ l += ['a', 'b']
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ l['a'] = 'foo'
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ c = l['c']
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ self.assertEqual(l['a'].foo, False)
++ l['a'].foo = True
++ self.assertEqual(l['a'].foo, True)
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ l['a'].bar = 'bar'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ self.assertEqual(l['a'].bar, 0)
++ l['a'].bar = 42
++ self.assertEqual(l['a'].bar, 42)
++@@ -354,10 +394,12 @@ class TestStrictOrderingOnAppendListWith
++ l['b'].foo = True
++ self.assertEqual(l['b'].foo, True)
++
++- with self.assertRaises(AttributeError):
+++ self.assertRaises(AttributeError).__enter__()
+++ if 1:
++ l['b'].baz = False
++
++
+++ self.assertRaises(AttributeError).__exit__(0, 0, 0)
++ class TestHierarchicalStringListWithFlagsFactory(unittest.TestCase):
++ def test_hierarchical_string_list_with_flags_factory(self):
++ cls = HierarchicalStringListWithFlagsFactory({
++@@ -368,19 +410,25 @@ class TestHierarchicalStringListWithFlag
++ l = cls()
++ l += ['a', 'b']
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ l['a'] = 'foo'
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ c = l['c']
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ self.assertEqual(l['a'].foo, False)
++ l['a'].foo = True
++ self.assertEqual(l['a'].foo, True)
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ l['a'].bar = 'bar'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ self.assertEqual(l['a'].bar, 0)
++ l['a'].bar = 42
++ self.assertEqual(l['a'].bar, 42)
++@@ -388,24 +436,32 @@ class TestHierarchicalStringListWithFlag
++ l['b'].foo = True
++ self.assertEqual(l['b'].foo, True)
++
++- with self.assertRaises(AttributeError):
+++ self.assertRaises(AttributeError).__enter__()
+++ if 1:
++ l['b'].baz = False
++
+++ self.assertRaises(AttributeError).__exit__(0, 0, 0)
++ l.x += ['x', 'y']
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ l.x['x'] = 'foo'
++
++- with self.assertRaises(Exception):
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
++ c = l.x['c']
++
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ self.assertEqual(l.x['x'].foo, False)
++ l.x['x'].foo = True
++ self.assertEqual(l.x['x'].foo, True)
++
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ l.x['x'].bar = 'bar'
++
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ self.assertEqual(l.x['x'].bar, 0)
++ l.x['x'].bar = 42
++ self.assertEqual(l.x['x'].bar, 42)
++@@ -413,9 +469,11 @@ class TestHierarchicalStringListWithFlag
++ l.x['y'].foo = True
++ self.assertEqual(l.x['y'].foo, True)
++
++- with self.assertRaises(AttributeError):
+++ self.assertRaises(AttributeError).__enter__()
+++ if 1:
++ l.x['y'].baz = False
++
++
+++ self.assertRaises(AttributeError).__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/util.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/util.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/util.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/util.py 2014-10-24 11:41:35.499880057 -0600
++@@ -1,3 +1,4 @@
+++from rhrebase import all
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++@@ -5,12 +6,12 @@
++ # This file contains miscellaneous utility functions that don't belong anywhere
++ # in particular.
++
++-from __future__ import unicode_literals
+++
++
++ import copy
++ import difflib
++ import errno
++-import hashlib
+++import sha
++ import os
++ import stat
++ import sys
++@@ -29,9 +30,10 @@ def hash_file(path):
++
++ # If the hashing function changes, this may invalidate lots of cached data.
++ # Don't change it lightly.
++- h = hashlib.sha1()
+++ h = sha.sha()
++
++- with open(path, 'rb') as fh:
+++ fh = open(path, 'rb')
+++ if 1:
++ while True:
++ data = fh.read(8192)
++
++@@ -40,6 +42,7 @@ def hash_file(path):
++
++ h.update(data)
++
+++ fh.close()
++ return h.hexdigest()
++
++
++@@ -122,7 +125,10 @@ class FileAvoidWrite(StringIO):
++ could add unwanted overhead to calls.
++ """
++ def __init__(self, filename, capture_diff=False):
++- StringIO.__init__(self)
+++ StringIO.__init__(self )
+++ #super(type(FileAvoidWrite), self).__init__()
+++ #print "SELF BUF", self.buf
+++ #super(FileAvoidWrite, self).__init__()
++ self.name = filename
++ self._capture_diff = capture_diff
++ self.diff = None
++@@ -138,7 +144,8 @@ class FileAvoidWrite(StringIO):
++ underlying file was changed, ``.diff`` will be populated with the diff
++ of the result.
++ """
++- buf = self.getvalue()
+++ buf = self.getvalue( )
+++ #buf = self.buf
++ StringIO.close(self)
++ existed = False
++ old_content = None
++@@ -155,16 +162,23 @@ class FileAvoidWrite(StringIO):
++ return True, False
++ except IOError:
++ pass
++- finally:
+++ if 1:
++ existing.close()
++
+++
++ ensureParentDir(self.name)
++- with open(self.name, 'w') as file:
+++ file = open(self.name, 'w')
+++ if 1:
++ file.write(buf)
++
+++ file.close()
++ if self._capture_diff:
++ try:
++- old_lines = old_content.splitlines() if old_content else []
+++ old_lines = None
+++ if old_content:
+++ old_lines = old_content.splitlines()
+++ else:
+++ old_lines = []
++ new_lines = buf.splitlines()
++
++ self.diff = difflib.unified_diff(old_lines, new_lines,
++@@ -181,8 +195,15 @@ class FileAvoidWrite(StringIO):
++ return existed, True
++
++ def __enter__(self):
+++ import traceback
+++ #print "ENTER:", self.buf
+++ #traceback.print_stack()
++ return self
++ def __exit__(self, type, value, traceback):
+++ #print "EXIT"
+++ import traceback
+++ #traceback.print_stack()
+++ #print self.buf
++ self.close()
++
++
++@@ -551,7 +572,7 @@ class LockFile(object):
++ try:
++ os.remove(self.lockfile)
++ break
++- except OSError as e:
+++ except OSError, e:
++ if e.errno == errno.EACCES:
++ # Another process probably has the file open, we'll retry.
++ # Just a short sleep since we want to drop the lock ASAP
++@@ -576,7 +597,7 @@ def lock_file(lockfile, max_wait = 600):
++ fd = os.open(lockfile, os.O_EXCL | os.O_RDWR | os.O_CREAT)
++ # We created the lockfile, so we're the owner
++ break
++- except OSError as e:
+++ except OSError, e:
++ if (e.errno == errno.EEXIST or
++ (sys.platform == "win32" and e.errno == errno.EACCES)):
++ pass
++@@ -589,7 +610,7 @@ def lock_file(lockfile, max_wait = 600):
++ # and read its contents to report the owner PID
++ f = open(lockfile, 'r')
++ s = os.stat(lockfile)
++- except EnvironmentError as e:
+++ except EnvironmentError, e:
++ if e.errno == errno.ENOENT or e.errno == errno.EACCES:
++ # We didn't create the lockfile, so it did exist, but it's
++ # gone now. Just try again
++@@ -613,7 +634,7 @@ def lock_file(lockfile, max_wait = 600):
++ # if we get here. we have the lockfile. Convert the os.open file
++ # descriptor into a Python file object and record our PID in it
++ f = os.fdopen(fd, 'w')
++- f.write('{0}\n'.format(os.getpid()))
+++ f.write('%d\n' %(os.getpid()))
++ f.close()
++
++ return LockFile(lockfile)
++diff -up comm-esr31/mozilla/python/mozbuild/mozbuild/virtualenv.py.python3 comm-esr31/mozilla/python/mozbuild/mozbuild/virtualenv.py
++--- comm-esr31/mozilla/python/mozbuild/mozbuild/virtualenv.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozbuild/virtualenv.py 2014-10-24 11:41:35.499880057 -0600
++@@ -1,11 +1,65 @@
++-# This Source Code Form is subject to the terms of the Mozilla Public
++-# License, v. 2.0. If a copy of the MPL was not distributed with this
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++ # This file contains code for populating the virtualenv environment for
++ # Mozilla's build system. It is typically called as part of configure.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file=sys.stdout):
+++ print file, msg
+++ file.write(msg)
++
++ import distutils.sysconfig
++ import os
++@@ -18,7 +72,7 @@ from distutils.version import StrictVers
++
++
++ # Minimum version of Python required to build.
++-MINIMUM_PYTHON_VERSION = StrictVersion('2.7.3')
+++MINIMUM_PYTHON_VERSION = StrictVersion('2.4')
++ MINIMUM_PYTHON_MAJOR = 2
++
++
++@@ -140,7 +194,9 @@ class VirtualenvManager(object):
++ args = [sys.executable, self.virtualenv_script_path,
++ self.virtualenv_root]
++
++- result = subprocess.call(args, stdout=self.log_handle,
+++# result = subprocess.call(args, stdout=self.log_handle,
+++# stderr=subprocess.STDOUT, env=env)
+++ result = subprocess.call(args,
++ stderr=subprocess.STDOUT, env=env)
++
++ if result:
++@@ -149,9 +205,11 @@ class VirtualenvManager(object):
++ return self.virtualenv_root
++
++ def packages(self):
++- with file(self.manifest_path, 'rU') as fh:
+++ fh = file(self.manifest_path, 'rU')
+++ if 1:
++ packages = [line.rstrip().split(':')
++ for line in fh]
+++ fh.close()
++ return packages
++
++ def populate(self):
++@@ -234,7 +292,8 @@ class VirtualenvManager(object):
++
++ path = os.path.join(self.topsrcdir, package[1])
++
++- with open(os.path.join(python_lib, package[0]), 'a') as f:
+++ f = open(os.path.join(python_lib, package[0]), 'a')
+++ if 1:
++ # This path is relative to the .pth file. Using a
++ # relative path allows the srcdir/objdir combination
++ # to be moved around (as long as the paths relative to
++@@ -245,6 +304,7 @@ class VirtualenvManager(object):
++ # When objdir is on a separate drive, relpath throws
++ f.write("%s\n" % os.path.join(python_lib, path))
++
+++ f.close()
++ return True
++
++ if package[0] == 'optional':
++@@ -252,18 +312,18 @@ class VirtualenvManager(object):
++ handle_package(package[1:])
++ return True
++ except:
++- print('Error processing command. Ignoring', \
++- 'because optional. (%s)' % ':'.join(package),
++- file=self.log_handle)
+++ print24('Error processing command. Ignoring because optional. (%s)' % ':'.join(package))
++ return False
++
++ if package[0] == 'objdir':
++ assert len(package) == 2
++ path = os.path.join(self.topobjdir, package[1])
++
++- with open(os.path.join(python_lib, 'objdir.pth'), 'a') as f:
+++ f = open(os.path.join(python_lib, 'objdir.pth'), 'a')
+++ if 1:
++ f.write('%s\n' % path)
++
+++ f.close()
++ return True
++
++ raise Exception('Unknown action: %s' % package[0])
++@@ -354,7 +414,7 @@ class VirtualenvManager(object):
++ try:
++ output = subprocess.check_output(program, cwd=directory, stderr=subprocess.STDOUT)
++ print(output)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ if 'Python.h: No such file or directory' in e.output:
++ print('WARNING: Python.h not found. Install Python development headers.')
++ else:
++@@ -458,7 +518,7 @@ if __name__ == '__main__':
++
++ topsrcdir, topobjdir, virtualenv_path, manifest_path = sys.argv[1:5]
++ populate = False
++-
+++ #print "MANIFEST PATH", manifest_path
++ # This should only be called internally.
++ if sys.argv[1] == 'populate':
++ populate = True
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/chrome/flags.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/chrome/flags.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/chrome/flags.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/chrome/flags.py 2014-10-24 11:41:35.499880057 -0600
++@@ -5,7 +5,7 @@
++ import re
++ from distutils.version import LooseVersion
++ from mozpack.errors import errors
++-from collections import OrderedDict
+++from ordereddict import OrderedDict
++
++
++ class Flag(object):
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/chrome/manifest.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/chrome/manifest.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/chrome/manifest.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/chrome/manifest.py 2014-10-24 11:41:35.500880053 -0600
++@@ -8,7 +8,7 @@ from urlparse import urlparse
++ import mozpack.path
++ from mozpack.chrome.flags import Flags
++ from mozpack.errors import errors
++-
+++from rhrebase import all, any
++
++ class ManifestEntry(object):
++ '''
++@@ -196,8 +196,8 @@ class ManifestOverload(ManifestEntry):
++ @property
++ def localized(self):
++ u = urlparse(self.overload)
++- return u.scheme == 'chrome' and \
++- u.path.split('/')[0:2] == ['', 'locale']
+++ return u[0] == 'chrome' and \
+++ u[1].split('/')[0:2] == ['', 'locale']
++
++
++ class ManifestOverlay(ManifestOverload):
++@@ -246,8 +246,10 @@ class ManifestResource(ManifestEntry):
++ return self.serialize(self.name, self.target)
++
++ def rebase(self, base):
+++ #print self.target
++ u = urlparse(self.target)
++- if u.scheme and u.scheme != 'jar':
+++ #print u, dir(u)
+++ if u[0] and u[0] != 'jar':
++ return ManifestEntry.rebase(self, base)
++ clone = ManifestEntry.rebase(self, base)
++ clone.target = mozpack.path.rebase(self.base, base, self.target)
++@@ -351,12 +353,14 @@ def parse_manifest(root, path, fileobj=N
++ linenum = 0
++ for line in fileobj:
++ linenum += 1
++- with errors.context(path, linenum):
+++ errors.context(path, linenum)
+++ if 1:
++ e = parse_manifest_line(base, line)
++ if e:
++ yield e
++
++
+++ #errors.context(path, linenum).__exit__(0, 0, 0)
++ def is_manifest(path):
++ '''
++ Return whether the given path is that of a manifest file.
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/copier.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/copier.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/copier.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/copier.py 2014-10-24 11:41:35.500880053 -0600
++@@ -12,11 +12,12 @@ from mozpack.files import (
++ )
++ import mozpack.path
++ import errno
++-from collections import (
++- Counter,
++- OrderedDict,
+++from mycollections import (
+++ namedtuple
++ )
+++from Counter import Counter
++
+++from ordereddict import OrderedDict
++
++ class FileRegistry(object):
++ '''
++@@ -50,10 +51,13 @@ class FileRegistry(object):
++ '''
++ Add a BaseFile instance to the container, under the given path.
++ '''
++- assert isinstance(content, BaseFile)
+++ assert isinstance(content, BaseFile)
++ if path in self._files:
++ return errors.error("%s already added" % path)
++- if self._required_directories[path] > 0:
+++ #print ("REQUIRED_DIRS")
+++ #print(self._required_directories)
+++ #print ("PATH IS "+ path)
+++ if self._required_directories.has_key(path) and self._required_directories[path] > 0:
++ return errors.error("Can't add %s: it is a required directory" %
++ path)
++ # Check whether any parent of the given path is already stored
++@@ -221,7 +225,7 @@ class FileCopier(FileRegistry):
++ # manage children of destination, not its parents.
++ try:
++ os.makedirs(destination)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++
++@@ -256,7 +260,7 @@ class FileCopier(FileRegistry):
++ for d in sorted(required_dirs, key=len):
++ try:
++ os.mkdir(d)
++- except OSError as error:
+++ except OSError, error:
++ if error.errno != errno.EEXIST:
++ raise
++
++@@ -468,11 +472,14 @@ class Jarrer(FileRegistry, BaseFile):
++ old_jar = JarReader(fileobj=dest)
++ except Exception:
++ old_jar = []
++-
+++ #print "old jar", old_jar
+++ #for f in old_jar:
+++ # print f.filename, f
++ old_contents = dict([(f.filename, f) for f in old_jar])
++-
++- with JarWriter(fileobj=dest, compress=self.compress,
++- optimize=self.optimize) as jar:
+++ #print "Old content", old_contents
+++ #print "JarWriter"
+++ jar = JarWriter(fileobj=dest, compress=self.compress, optimize=self.optimize).__enter__()
+++ if 1:
++ for path, file in self:
++ if path in old_contents:
++ deflater = DeflaterDest(old_contents[path], self.compress)
++@@ -483,6 +490,7 @@ class Jarrer(FileRegistry, BaseFile):
++ if self._preload:
++ jar.preload(self._preload)
++
+++ jar.__exit__(0, 0, 0)
++ def open(self):
++ raise RuntimeError('unsupported')
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/errors.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/errors.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/errors.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/errors.py 2014-10-24 11:41:35.500880053 -0600
++@@ -3,7 +3,7 @@
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++ import sys
++-from contextlib import contextmanager
+++
++
++
++ class ErrorMessage(Exception):
++@@ -38,30 +38,40 @@ class ErrorCollector(object):
++ information when a context is provided. Context is defined by a pair
++ (filename, linenumber), and may be set with errors.context() used as a
++ context manager:
++- with errors.context(filename, linenumber):
+++ errors.context(filename, linenumber).__enter__()
+++ if 1:
++ errors.warn(message)
++
+++ errors.context(filename, linenumber).__exit__(0, 0, 0)
++ Arbitrary nesting is supported, both for errors.context calls:
++- with errors.context(filename1, linenumber1):
+++ errors.context(filename1, linenumber1).__enter__()
+++ if 1:
++ errors.warn(message)
++- with errors.context(filename2, linenumber2):
+++ errors.context(filename2, linenumber2).__enter__()
+++ if 1:
++ errors.warn(message)
++
+++ errors.context(filename2, linenumber2).__exit__(0, 0, 0)
+++ errors.context(filename1, linenumber1).__exit__(0, 0, 0)
++ as well as for function calls:
++ def func():
++ errors.warn(message)
++- with errors.context(filename, linenumber):
+++ errors.context(filename, linenumber).__enter__()
+++ if 1:
++ func()
++
+++ errors.context(filename, linenumber).__exit__(0, 0, 0)
++ Errors and fatal errors can have their exception thrown at a later time,
++ allowing for several different errors to be reported at once before
++ throwing. This is achieved with errors.accumulate() as a context manager:
++- with errors.accumulate():
+++ errors.accumulate().__enter__()
+++ if 1:
++ if test1:
++ errors.error(message1)
++ if test2:
++ errors.error(message2)
++
+++ errors.accumulate().__exit__(0, 0, 0)
++ In such cases, a single AccumulatedErrors exception is thrown, but doesn't
++ contain information about the exceptions. The logged messages do.
++ '''
++@@ -110,19 +120,19 @@ class ErrorCollector(object):
++ if self._context:
++ return self._context[-1]
++
++- @contextmanager
+++ #@contextmanager
++ def context(self, file, line):
++ if file and line:
++ self._context.append((file, line))
++- yield
+++ # just for now yield
++ if file and line:
++ self._context.pop()
++
++- @contextmanager
+++ #@contextmanager
++ def accumulate(self):
++ assert self._count is None
++ self._count = 0
++- yield
+++ #just for now yield
++ count = self._count
++ self._count = None
++ if count:
++@@ -131,7 +141,10 @@ class ErrorCollector(object):
++ @property
++ def count(self):
++ # _count can be None.
++- return self._count if self._count else 0
+++ if self._count:
+++ return self._count
+++ else:
+++ return 0
++
++
++ errors = ErrorCollector()
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/executables.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/executables.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/executables.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/executables.py 2014-10-24 11:41:35.500880053 -0600
++@@ -27,7 +27,8 @@ def get_type(path):
++ Check the signature of the give file and returns what kind of executable
++ matches.
++ '''
++- with open(path, 'rb') as f:
+++ f = open(path, 'rb')
+++ if 1:
++ signature = f.read(4)
++ if len(signature) < 4:
++ return UNKNOWN
++@@ -54,6 +55,7 @@ def get_type(path):
++ return UNKNOWN
++
++
+++ f.close()
++ def is_executable(path):
++ '''
++ Return whether a given file path points to an executable or a library,
++@@ -92,7 +94,11 @@ def strip(path):
++ '''
++ from buildconfig import substs
++ strip = substs['STRIP']
++- flags = substs['STRIP_FLAGS'].split() if 'STRIP_FLAGS' in substs else []
+++ flags = None
+++ if 'STRIP_FLAGS' in substs:
+++ flags = substs['STRIP_FLAGS'].split()
+++ else:
+++ flags = []
++ cmd = [strip] + flags + [path]
++ if subprocess.call(cmd) != 0:
++ errors.fatal('Error executing ' + ' '.join(cmd))
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/files.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/files.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/files.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/files.py 2014-10-24 11:41:35.501880049 -0600
++@@ -20,14 +20,14 @@ from mozpack.executables import (
++ elfhack,
++ )
++ from mozpack.chrome.manifest import ManifestEntry
++-from io import BytesIO
+++from StringIO import StringIO as BytesIO
++ from mozpack.errors import (
++ ErrorMessage,
++ errors,
++ )
++ from mozpack.mozjar import JarReader
++ import mozpack.path
++-from collections import OrderedDict
+++from ordereddict import OrderedDict
++ from jsmin import JavascriptMinify
++ from tempfile import (
++ mkstemp,
++@@ -215,8 +215,10 @@ class ExecutableFile(File):
++ return False
++ try:
++ if may_strip(dest):
+++ #print "strip", dest
++ strip(dest)
++ if may_elfhack(dest):
+++ #print "elfhack", dest
++ elfhack(dest)
++ except ErrorMessage:
++ os.remove(dest)
++@@ -263,7 +265,7 @@ class AbsoluteSymlinkFile(File):
++
++ try:
++ st = os.lstat(dest)
++- except OSError as ose:
+++ except OSError, ose:
++ if ose.errno != errno.ENOENT:
++ raise
++
++@@ -394,11 +396,13 @@ class PreprocessedFile(BaseFile):
++ # dependencies from that file to our list.
++ if self.depfile and os.path.exists(self.depfile):
++ target = mozpack.path.normpath(dest.name)
++- with open(self.depfile, 'rb') as fileobj:
+++ fileobj = open(self.depfile, 'rb')
+++ if 1:
++ for rule in makeutil.read_dep_makefile(fileobj):
++ if target in rule.targets():
++ pp_deps.update(rule.dependencies())
++
+++ fileobj.close()
++ skip = False
++ if dest.exists() and skip_if_older:
++ # If a dependency file was specified, and it doesn't exist,
++@@ -417,9 +421,11 @@ class PreprocessedFile(BaseFile):
++ deps_out = FileAvoidWrite(self.depfile)
++ pp = Preprocessor(defines=self.defines, marker=self.marker)
++
++- with open(self.path, 'rU') as input:
+++ input = open(self.path, 'rU')
+++ if 1:
++ pp.processFile(input=input, output=dest, depfile=deps_out)
++
+++ input.close()
++ dest.close()
++ if self.depfile:
++ deps_out.close()
++@@ -541,7 +547,11 @@ class ManifestFile(BaseFile):
++ currently but could in the future.
++ '''
++ def __init__(self, base, entries=None):
++- self._entries = entries if entries else []
+++ self._entries = None
+++ if entries:
+++ self._entries = entries
+++ else:
+++ self._entries = []
++ self._base = base
++
++ def add(self, entry):
++@@ -619,7 +629,10 @@ class MinifiedJavaScript(BaseFile):
++ input_source = self._file.open().read()
++ output_source = output.getvalue()
++
++- with NamedTemporaryFile() as fh1, NamedTemporaryFile() as fh2:
+++ fh1 = NamedTemporaryFile().__enter__()
+++ fh2 = NamedTemporaryFile().__enter__()
+++ if 1:
+++ #with NamedTemporaryFile() as fh1, NamedTemporaryFile() as fh2:
++ fh1.write(input_source)
++ fh2.write(output_source)
++ fh1.flush()
++@@ -629,7 +642,7 @@ class MinifiedJavaScript(BaseFile):
++ args = list(self._verify_command)
++ args.extend([fh1.name, fh2.name])
++ subprocess.check_output(args, stderr=subprocess.STDOUT)
++- except subprocess.CalledProcessError as e:
+++ except subprocess.CalledProcessError, e:
++ errors.warn('JS minification verification failed for %s:' %
++ (getattr(self._file, 'path', '<unknown>')))
++ # Prefix each line with "Warning:" so mozharness doesn't
++@@ -638,6 +651,8 @@ class MinifiedJavaScript(BaseFile):
++ errors.warn(line)
++
++ return self._file.open()
+++ fh1.close()
+++ fh2.close()
++
++ return output
++
++@@ -685,9 +700,10 @@ class BaseFinder(object):
++ '''
++ Iterates over all files under the base directory (excluding files
++ starting with a '.' and files at any level under a directory starting
++- with a '.').
++- for path, file in finder:
+++ a '.'). for path, file in finder.__enter__()
+++ if 1:
++ ...
+++ a '.'). for path, file in finder.__exit__(0, 0, 0)
++ '''
++ return self.find('')
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/manifests.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/manifests.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/manifests.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/manifests.py 2014-10-24 11:41:35.501880049 -0600
++@@ -2,12 +2,12 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
++
++-from contextlib import contextmanager
++-import json
++
++-from .files import (
+++
+++import simplejson as json
+++
+++from files import (
++ AbsoluteSymlinkFile,
++ ExistingFile,
++ File,
++@@ -15,7 +15,7 @@ from .files import (
++ PreprocessedFile,
++ )
++ import mozpack.path as mozpath
++-
+++from contextdecorator import contextmanager
++
++ # This probably belongs in a more generic module. Where?
++ @contextmanager
++@@ -29,11 +29,10 @@ def _auto_fileobj(path, fileobj, mode='r
++ if path:
++ fileobj = open(path, mode)
++
++- try:
++- yield fileobj
++- finally:
++- if path:
++- fileobj.close()
+++ #try:
+++ yield fileobj
+++ if path:
+++ fileobj.close()
++
++
++ class UnreadableInstallManifest(Exception):
++@@ -108,10 +107,13 @@ class InstallManifest(object):
++ self._source_file = None
++
++ if path or fileobj:
++- with _auto_fileobj(path, fileobj, 'rb') as fh:
+++ fh = _auto_fileobj(path, fileobj, 'rb').__enter__()
+++ if 1:
++ self._source_file = fh.name
++ self._load_from_fileobj(fh)
++
+++ #fh.__exit__(0, 0, 0)
+++ #fh.close()
++ def _load_from_fileobj(self, fileobj):
++ version = fileobj.readline().rstrip()
++ if version not in ('1', '2', '3', '4'):
++@@ -209,7 +211,8 @@ class InstallManifest(object):
++
++ It is an error if both are specified.
++ """
++- with _auto_fileobj(path, fileobj, 'wb') as fh:
+++ fh = _auto_fileobj(path, fileobj, 'wb').__enter__()
+++ if 1:
++ fh.write('%d\n' % self.CURRENT_VERSION)
++
++ for dest in sorted(self._dests):
++@@ -220,6 +223,7 @@ class InstallManifest(object):
++ fh.write('%s\n' % self.FIELD_SEPARATOR.join(
++ p.encode('utf-8') for p in parts))
++
+++ #fh.close()
++ def add_symlink(self, source, dest):
++ """Add a symlink to this manifest.
++
++@@ -289,7 +293,10 @@ class InstallManifest(object):
++ self._dests[dest] = entry
++
++ def _get_deps(self, dest):
++- return {self._source_file} if self._source_file else set()
+++ if self._source_file:
+++ return (self._source_file)
+++ else:
+++ return set()
++
++ def populate_registry(self, registry):
++ """Populate a mozpack.copier.FileRegistry instance with data from us.
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/mozjar.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/mozjar.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/mozjar.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/mozjar.py 2014-10-24 11:41:35.501880049 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from io import BytesIO
+++from StringIO import StringIO as BytesIO
++ import struct
++ import zlib
++ import os
++@@ -10,8 +10,9 @@ from zipfile import (
++ ZIP_STORED,
++ ZIP_DEFLATED,
++ )
++-from collections import OrderedDict
++-from urlparse import urlparse, ParseResult
+++from ordereddict import OrderedDict
+++from urlparse import urlparse
+++# ParseResult
++ import mozpack.path
++
++ JAR_STORED = ZIP_STORED
++@@ -94,8 +95,6 @@ class JarStruct(object):
++ else:
++ size = sizes[t]
++ value = data[offset:offset + size]
++- if isinstance(value, memoryview):
++- value = value.tobytes()
++ if not name in sizes:
++ self._values[name] = value
++ else:
++@@ -110,7 +109,11 @@ class JarStruct(object):
++ for name, t in self.STRUCT.iteritems():
++ if name in self.size_fields:
++ continue
++- self._values[name] = 0 if t in JarStruct.TYPE_MAPPING else ''
+++ self._values[name] = None
+++ if t in JarStruct.TYPE_MAPPING:
+++ self._values[name] = 0
+++ else:
+++ self._values[name] = ''
++
++ @staticmethod
++ def get_data(type, data):
++@@ -122,8 +125,6 @@ class JarStruct(object):
++ assert data is not None
++ format, size = JarStruct.TYPE_MAPPING[type]
++ data = data[:size]
++- if isinstance(data, memoryview):
++- data = data.tobytes()
++ return struct.unpack('<' + format, data)[0], size
++
++ def serialize(self):
++@@ -261,12 +262,12 @@ class JarFileReader(object):
++ the file data.
++ '''
++ assert header['compression'] in [JAR_DEFLATED, JAR_STORED]
++- self._data = data
++ # Copy some local file header fields.
++ for name in ['filename', 'compressed_size',
++ 'uncompressed_size', 'crc32']:
++ setattr(self, name, header[name])
++ self.compressed = header['compression'] == JAR_DEFLATED
+++ self._data = data[:header['compressed_size']]
++
++ def read(self, length=-1):
++ '''
++@@ -287,7 +288,7 @@ class JarFileReader(object):
++ '''
++ return iter(self.readlines())
++
++- def seek(self, pos, whence=os.SEEK_SET):
+++ def seek(self, pos, whence=0):
++ '''
++ Change the current position in the uncompressed data. Subsequent reads
++ will start from there.
++@@ -316,9 +317,7 @@ class JarFileReader(object):
++ return self._uncompressed_data
++ data = self.compressed_data
++ if self.compressed:
++- data = zlib.decompress(data.tobytes(), -MAX_WBITS)
++- else:
++- data = data.tobytes()
+++ data = zlib.decompress(data, -MAX_WBITS)
++ if len(data) != self.uncompressed_size:
++ raise JarReaderError('Corrupted file? %s' % self.filename)
++ self._uncompressed_data = BytesIO(data)
++@@ -339,7 +338,7 @@ class JarReader(object):
++ data = fileobj.read()
++ else:
++ data = open(file, 'rb').read()
++- self._data = memoryview(data)
+++ self._data = buffer(data)
++ # The End of Central Directory Record has a variable size because of
++ # comments it may contain, so scan for it from the end of the file.
++ offset = -CDIR_END_SIZE
++@@ -666,8 +665,6 @@ class Deflater(object):
++ self._data.write(data)
++ if self.compress:
++ if self._deflater:
++- if isinstance(data, memoryview):
++- data = data.tobytes()
++ self._deflated.write(self._deflater.compress(data))
++ else:
++ raise JarWriterError("Can't write after flush")
++@@ -780,6 +777,7 @@ class JarLog(dict):
++ - jar:jar:file:///{path}!/{subpath}!/{subpath2} becomes
++ ({path}, {subpath}, {subpath2})
++ '''
+++ #print url, dir(url)
++ if not isinstance(url, ParseResult):
++ # Assume that if it doesn't start with jar: or file:, it's a path.
++ if not url.startswith(('jar:', 'file:')):
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/packager/formats.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/packager/formats.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/packager/formats.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/packager/formats.py 2014-10-24 11:41:35.502880045 -0600
++@@ -2,6 +2,8 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
+++from rhrebase import all, any
+++
++ from mozpack.chrome.manifest import (
++ Manifest,
++ ManifestInterfaces,
++@@ -100,8 +102,7 @@ class FlatFormatter(object):
++ '%s.manifest' % name))
++ if not self.copier.contains(path):
++ assert mozpack.path.basedir(entry.base, [base]) == base
++- # Add a reference to the manifest file in the parent manifest, if
++- # the manifest file is not a root manifest.
+++ # Add a reference to the manifest file in the parent manifest, if # the manifest file is not a root manifest.
++ if len(entry.base) > len(base):
++ parent = mozpack.path.dirname(entry.base)
++ relbase = mozpack.path.basename(entry.base)
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/packager/__init__.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/packager/__init__.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/packager/__init__.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/packager/__init__.py 2014-10-24 11:41:35.502880045 -0600
++@@ -99,7 +99,11 @@ class Component(object):
++ raise ValueError('No component found')
++ if not re.match('[a-zA-Z0-9_\-]+$', component):
++ raise ValueError('Bad component name ' + component)
++- options = Component._split_options(splits[1]) if len(splits) > 1 else {}
+++ options = None
+++ if len(splits) > 1:
+++ options = Component._split_options(splits[1])
+++ else:
+++ options = {}
++ return component, options
++
++ @staticmethod
++@@ -109,7 +113,7 @@ class Component(object):
++ '''
++ try:
++ name, options = Component._split_component_and_options(string)
++- except ValueError as e:
+++ except ValueError, e:
++ errors.fatal('Malformed manifest: %s' % e)
++ return
++ destdir = options.pop('destdir', '')
++@@ -174,10 +178,12 @@ class PreprocessorOutputWrapper(object):
++
++ def write(self, str):
++ file = os.path.normpath(os.path.abspath(self._pp.context['FILE']))
++- with errors.context(file, self._pp.context['LINE']):
+++ errors.context(file, self._pp.context['LINE'])
+++ if 1:
++ self._parser.handle_line(str)
++
++
+++ #errors.context(file, self._pp.context['LINE']).__exit__(0, 0, 0)
++ def preprocess(input, parser, defines={}):
++ '''
++ Preprocess the file-like input with the given defines, and send the
++@@ -213,8 +219,10 @@ class CallDeque(deque):
++ except IndexError:
++ return
++ if context:
++- with errors.context(context[0], context[1]):
+++ errors.context(context[0], context[1]).__enter__()
+++ if 1:
++ function(*args)
+++ errors.context(context[0], context[1]).__exit__(0, 0, 0)
++ else:
++ function(*args)
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/packager/l10n.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/packager/l10n.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/packager/l10n.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/packager/l10n.py 2014-10-24 11:41:35.502880045 -0600
++@@ -168,7 +168,9 @@ def repack(source, l10n, non_resources=[
++ optimize=app_finder.optimizedjars,
++ non_resources=non_resources)
++
++- with errors.accumulate():
+++ errors.accumulate().__enter__()
+++ if 1:
++ _repack(app_finder, l10n_finder, copier, formatter, non_chrome)
+++ errors.accumulate().__exit__(0, 0, 0)
++ copier.copy(source, skip_if_older=False)
++ generate_precomplete(source)
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/packager/unpack.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/packager/unpack.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/packager/unpack.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/packager/unpack.py 2014-10-24 11:41:35.502880045 -0600
++@@ -68,8 +68,11 @@ class UnpackFinder(FileFinder):
++ # jar: urls. If there are some, the files contained in the jar they
++ # point to, go under a directory named after the jar.
++ if is_manifest(p):
++- m = self.files[p] if self.files.contains(p) \
++- else ManifestFile(base)
+++ m = None
+++ if self.files.contains(p):
+++ m = self.files[p]
+++ else:
+++ m = ManifestFile(base)
++ for e in parse_manifest(self.base, p, f.open()):
++ m.add(self._handle_manifest_entry(e, jars))
++ if self.files.contains(p):
++@@ -82,8 +85,11 @@ class UnpackFinder(FileFinder):
++ for j in jar:
++ path = mozpack.path.join(base, j.filename)
++ if is_manifest(j.filename):
++- m = self.files[path] if self.files.contains(path) \
++- else ManifestFile(mozpack.path.dirname(path))
+++ m = None
+++ if self.files.contains(path):
+++ m = self.files[path]
+++ else:
+++ m = ManifestFile(mozpack.path.dirname(path))
++ for e in parse_manifest(None, path, j):
++ m.add(e)
++ if not self.files.contains(path):
++@@ -95,10 +101,10 @@ class UnpackFinder(FileFinder):
++ def _handle_manifest_entry(self, entry, jars):
++ jarpath = None
++ if isinstance(entry, ManifestEntryWithRelPath) and \
++- urlparse(entry.relpath).scheme == 'jar':
+++ urlparse(entry.relpath)[0] == 'jar':
++ jarpath, entry = self._unjarize(entry, entry.relpath)
++ elif isinstance(entry, ManifestResource) and \
++- urlparse(entry.target).scheme == 'jar':
+++ urlparse(entry.target)[0] == 'jar':
++ jarpath, entry = self._unjarize(entry, entry.target)
++ if jarpath:
++ # Don't defer unpacking the jar file. If we already saw
++@@ -153,7 +159,7 @@ class UnpackFinder(FileFinder):
++ the new entry.
++ '''
++ base = entry.base
++- jar, relpath = urlparse(relpath).path.split('!', 1)
+++ jar, relpath = urlparse(relpath)[1].split('!', 1)
++ entry = entry.rebase(mozpack.path.join(base, 'jar:%s!' % jar)) \
++ .move(mozpack.path.join(base, mozpack.path.splitext(jar)[0])) \
++ .rebase(base)
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/path.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/path.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/path.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/path.py 2014-10-24 11:41:35.503880041 -0600
++@@ -1,6 +1,60 @@
++ # This Source Code Form is subject to the terms of the Mozilla Public
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+++# relpath
+++import os, sys
+++# Creates os.path.relpath for Python 2.4
+++
+++if not hasattr(os, "relpath"):
+++ if os.path is sys.modules.get("ntpath"):
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++ if start_list[0].lower() != path_list[0].lower():
+++ unc_path, rest = os.path.splitunc(path)
+++ unc_start, rest = os.path.splitunc(start)
+++ if bool(unc_path) ^ bool(unc_start):
+++ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+++ % (path, start))
+++ else:
+++ raise ValueError("path is on drive %s, start on drive %s"
+++ % (path_list[0], start_list[0]))
+++ # Work out how much of the filepath is shared by start and path.
+++ for i in range(min(len(start_list), len(path_list))):
+++ if start_list[i].lower() != path_list[i].lower():
+++ break
+++ else:
+++ i += 1
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ else:
+++ # default to posixpath definition
+++ def relpath(path, start=os.path.curdir):
+++ """Return a relative version of a path"""
+++
+++ if not path:
+++ raise ValueError("no path specified")
+++
+++ start_list = os.path.abspath(start).split(os.path.sep)
+++ path_list = os.path.abspath(path).split(os.path.sep)
+++
+++ # Work out how much of the filepath is shared by start and path.
+++ i = len(os.path.commonprefix([start_list, path_list]))
+++
+++ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+++ if not rel_list:
+++ return os.path.curdir
+++ return os.path.join(*rel_list)
+++
+++ os.path.relpath = relpath
++
++ import posixpath
++ import os
++@@ -25,7 +79,10 @@ def normsep(path):
++
++ def relpath(path, start):
++ rel = normsep(os.path.relpath(path, start))
++- return '' if rel == '.' else rel
+++ if rel == '.':
+++ return ''
+++ else:
+++ return rel
++
++
++ def abspath(path):
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py 2014-10-24 11:41:35.503880041 -0600
++@@ -131,7 +131,8 @@ class TestManifestErrors(TestErrors, uni
++ 'binary-component bar.so',
++ 'unsupported foo',
++ ]
++- with mozunit.MockedOpen({'manifest': '\n'.join(manifest)}):
+++ mozunit.MockedOpen({'manifest': '\n'.join(manifest)}).__enter__()
+++ if 1:
++ with self.assertRaises(AccumulatedErrors):
++ with errors.accumulate():
++ list(parse_manifest(os.curdir, 'manifest'))
++@@ -145,5 +146,6 @@ class TestManifestErrors(TestErrors, uni
++ self.assertTrue(out[1].startswith('Error: %s:4: ' % path))
++
++
+++ mozunit.MockedOpen({'manifest': '\n'.join(manifest)}).__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ mozunit.main()
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_copier.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_copier.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_copier.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_copier.py 2014-10-24 11:41:35.503880041 -0600
++@@ -290,13 +290,17 @@ class TestFileCopier(TestWithTmpDir):
++
++ def test_permissions(self):
++ """Ensure files without write permission can be deleted."""
++- with open(self.tmppath('dummy'), 'a'):
+++ open(self.tmppath('dummy'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('dummy'), 'a').__exit__(0, 0, 0)
++ p = self.tmppath('no_perms')
++- with open(p, 'a'):
+++ open(p, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(p, 'a').__exit__(0, 0, 0)
++ # Make file and directory unwritable. Reminder: making a directory
++ # unwritable prevents modifications (including deletes) from the list
++ # of files in that directory.
++@@ -313,16 +317,20 @@ class TestFileCopier(TestWithTmpDir):
++ copier = FileCopier()
++ copier.add('foo', GeneratedFile('foo'))
++
++- with open(self.tmppath('bar'), 'a'):
+++ open(self.tmppath('bar'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('bar'), 'a').__exit__(0, 0, 0)
++ os.mkdir(self.tmppath('emptydir'))
++ d = self.tmppath('populateddir')
++ os.mkdir(d)
++
++- with open(self.tmppath('populateddir/foo'), 'a'):
+++ open(self.tmppath('populateddir/foo'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('populateddir/foo'), 'a').__exit__(0, 0, 0)
++ result = copier.copy(self.tmpdir, remove_unaccounted=False)
++
++ self.assertEqual(self.all_files(self.tmpdir), set(['foo', 'bar',
++@@ -336,16 +344,20 @@ class TestFileCopier(TestWithTmpDir):
++ copier = FileCopier()
++ copier.add('foo', GeneratedFile('foo'))
++
++- with open(self.tmppath('bar'), 'a'):
+++ open(self.tmppath('bar'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('bar'), 'a').__exit__(0, 0, 0)
++ os.mkdir(self.tmppath('emptydir'))
++ d = self.tmppath('populateddir')
++ os.mkdir(d)
++
++- with open(self.tmppath('populateddir/foo'), 'a'):
+++ open(self.tmppath('populateddir/foo'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('populateddir/foo'), 'a').__exit__(0, 0, 0)
++ result = copier.copy(self.tmpdir, remove_unaccounted=False,
++ remove_empty_directories=False)
++
++@@ -390,16 +402,22 @@ class TestFilePurger(TestWithTmpDir):
++ extra = os.path.join(self.tmpdir, 'extra')
++ empty_dir = os.path.join(self.tmpdir, 'dir')
++
++- with open(existing, 'a'):
+++ open(existing, 'a').__enter__()
+++ if 1:
++ pass
++
++- with open(extra, 'a'):
+++ open(existing, 'a').__exit__(0, 0, 0)
+++ open(extra, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(extra, 'a').__exit__(0, 0, 0)
++ os.mkdir(empty_dir)
++- with open(os.path.join(empty_dir, 'foo'), 'a'):
+++ open(os.path.join(empty_dir, 'foo'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(os.path.join(empty_dir, 'foo'), 'a').__exit__(0, 0, 0)
++ self.assertTrue(os.path.exists(existing))
++ self.assertTrue(os.path.exists(extra))
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_errors.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_errors.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_errors.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_errors.py 2014-10-24 11:41:35.503880041 -0600
++@@ -40,25 +40,32 @@ class TestErrorsImpl(TestErrors, unittes
++ self.assertEquals(self.get_output(), ['Warning: foo', 'Warning: bar'])
++
++ def test_no_error(self):
++- with errors.accumulate():
+++ errors.accumulate().__enter__()
+++ if 1:
++ errors.warn('1')
++
+++ errors.accumulate().__exit__(0, 0, 0)
++ def test_simple_error(self):
++- with self.assertRaises(AccumulatedErrors):
+++ self.assertRaises(AccumulatedErrors).__enter__()
+++ if 1:
++ with errors.accumulate():
++ errors.error('1')
+++ self.assertRaises(AccumulatedErrors).__exit__(0, 0, 0)
++ self.assertEquals(self.get_output(), ['Error: 1'])
++
++ def test_error_loop(self):
++- with self.assertRaises(AccumulatedErrors):
+++ self.assertRaises(AccumulatedErrors).__enter__()
+++ if 1:
++ with errors.accumulate():
++ for i in range(3):
++ errors.error('%d' % i)
+++ self.assertRaises(AccumulatedErrors).__exit__(0, 0, 0)
++ self.assertEquals(self.get_output(),
++ ['Error: 0', 'Error: 1', 'Error: 2'])
++
++ def test_multiple_errors(self):
++- with self.assertRaises(AccumulatedErrors):
+++ self.assertRaises(AccumulatedErrors).__enter__()
+++ if 1:
++ with errors.accumulate():
++ errors.error('foo')
++ for i in range(3):
++@@ -67,12 +74,14 @@ class TestErrorsImpl(TestErrors, unittes
++ else:
++ errors.error('%d' % i)
++ errors.error('bar')
+++ self.assertRaises(AccumulatedErrors).__exit__(0, 0, 0)
++ self.assertEquals(self.get_output(),
++ ['Error: foo', 'Error: 0', 'Error: 1',
++ 'Warning: 2', 'Error: bar'])
++
++ def test_errors_context(self):
++- with self.assertRaises(AccumulatedErrors):
+++ self.assertRaises(AccumulatedErrors).__enter__()
+++ if 1:
++ with errors.accumulate():
++ self.assertEqual(errors.get_context(), None)
++ with errors.context('foo', 1):
++@@ -83,6 +92,7 @@ class TestErrorsImpl(TestErrors, unittes
++ errors.error('b')
++ self.assertEqual(errors.get_context(), ('foo', 1))
++ errors.error('c')
+++ self.assertRaises(AccumulatedErrors).__exit__(0, 0, 0)
++ self.assertEqual(self.get_output(), [
++ 'Error: foo:1: a',
++ 'Error: bar:2: b',
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_files.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_files.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_files.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_files.py 2014-10-24 11:41:35.504880036 -0600
++@@ -53,9 +53,11 @@ class TestWithTmpDir(unittest.TestCase):
++ return
++
++ dummy_path = self.tmppath('dummy_file')
++- with open(dummy_path, 'a'):
+++ open(dummy_path, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(dummy_path, 'a').__exit__(0, 0, 0)
++ try:
++ os.symlink(dummy_path, self.tmppath('dummy_symlink'))
++ os.remove(self.tmppath('dummy_symlink'))
++@@ -153,8 +155,10 @@ class TestFile(TestWithTmpDir):
++ dest = self.tmppath('dest')
++
++ for content in samples:
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb')
+++ if 1:
++ tmp.write(content)
+++ tmp.__exit__(0, 0, 0)
++ # Ensure the destination file, when it exists, is older than the
++ # source
++ if os.path.exists(dest):
++@@ -177,8 +181,10 @@ class TestFile(TestWithTmpDir):
++ dest = MockDest()
++
++ for content in samples:
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write(content)
+++ tmp.close()
++ f = File(src)
++ f.copy(dest)
++ self.assertEqual(content, dest.getvalue())
++@@ -189,9 +195,11 @@ class TestFile(TestWithTmpDir):
++ '''
++ src = self.tmppath('src')
++ content = ''.join(samples)
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb')
+++ if 1:
++ tmp.write(content)
++
+++ tmp.__exit__(0, 0, 0)
++ f = File(src)
++ self.assertEqual(content[:42], f.open().read(42))
++ self.assertEqual(content, f.open().read())
++@@ -204,9 +212,11 @@ class TestFile(TestWithTmpDir):
++ src = self.tmppath('src')
++ dest = self.tmppath('dest')
++
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb')
+++ if 1:
++ tmp.write('test')
++
+++ tmp.__exit__(0, 0, 0)
++ # Initial copy
++ f = File(src)
++ f.copy(dest)
++@@ -224,8 +234,10 @@ class TestFile(TestWithTmpDir):
++
++ # When the source file is older than the destination file, even with
++ # different content, no copy should occur.
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('fooo')
+++ tmp.__exit__(0, 0, 0)
++ time = os.path.getmtime(dest) - 1
++ os.utime(src, (time, time))
++ f.copy(DestNoWrite(dest))
++@@ -246,14 +258,18 @@ class TestAbsoluteSymlinkFile(TestWithTm
++ def test_absolute_relative(self):
++ AbsoluteSymlinkFile('/foo')
++
++- with self.assertRaisesRegexp(ValueError, 'Symlink target not absolute'):
+++ self.assertRaisesRegexp(ValueError, 'Symlink target not absolute').__enter__()
+++ if 1:
++ AbsoluteSymlinkFile('./foo')
++
+++ self.assertRaisesRegexp(ValueError, 'Symlink target not absolute').__exit__(0, 0, 0)
++ def test_symlink_file(self):
++ source = self.tmppath('test_path')
++- with open(source, 'wt') as fh:
+++ fh = open(source, 'wt').__enter__()
+++ if 1:
++ fh.write('Hello world')
++
+++ fh.__exit__(0, 0, 0)
++ s = AbsoluteSymlinkFile(source)
++ dest = self.tmppath('symlink')
++ self.assertTrue(s.copy(dest))
++@@ -271,13 +287,17 @@ class TestAbsoluteSymlinkFile(TestWithTm
++ # If symlinks are supported, an existing file should be replaced by a
++ # symlink.
++ source = self.tmppath('test_path')
++- with open(source, 'wt') as fh:
+++ fh = open(source, 'wt').__enter__()
+++ if 1:
++ fh.write('source')
++
+++ fh.__exit__(0, 0, 0)
++ dest = self.tmppath('dest')
++- with open(dest, 'a'):
+++ open(dest, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(dest, 'a').__exit__(0, 0, 0)
++ s = AbsoluteSymlinkFile(source)
++ s.copy(dest, skip_if_older=False)
++
++@@ -295,9 +315,11 @@ class TestAbsoluteSymlinkFile(TestWithTm
++ return
++
++ source = self.tmppath('source')
++- with open(source, 'a'):
+++ open(source, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(source, 'a').__exit__(0, 0, 0)
++ dest = self.tmppath('dest')
++
++ os.symlink(self.tmppath('bad'), dest)
++@@ -317,9 +339,11 @@ class TestAbsoluteSymlinkFile(TestWithTm
++ source = self.tmppath('source')
++ dest = self.tmppath('dest')
++
++- with open(source, 'a'):
+++ open(source, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(source, 'a').__exit__(0, 0, 0)
++ os.symlink(source, dest)
++ link = os.readlink(dest)
++ self.assertEqual(link, source)
++@@ -338,9 +362,11 @@ class TestPreprocessedFile(TestWithTmpDi
++ src = self.tmppath('src')
++ dest = self.tmppath('dest')
++
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('#ifdef FOO\ntest\n#endif')
++
+++ tmp.__exit__(0, 0, 0)
++ f = PreprocessedFile(src, depfile_path=None, marker='#', defines={'FOO': True})
++ self.assertTrue(f.copy(dest))
++
++@@ -355,9 +381,11 @@ class TestPreprocessedFile(TestWithTmpDi
++ dest = self.tmppath('dest')
++ depfile = self.tmppath('depfile')
++
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('#ifdef FOO\ntest\n#endif')
++
+++ tmp.__exit__(0, 0, 0)
++ # Initial copy
++ f = PreprocessedFile(src, depfile_path=depfile, marker='#', defines={'FOO': True})
++ self.assertTrue(f.copy(dest))
++@@ -368,8 +396,10 @@ class TestPreprocessedFile(TestWithTmpDi
++
++ # When the source file is older than the destination file, even with
++ # different content, no copy should occur.
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('#ifdef FOO\nfooo\n#endif')
+++ tmp.__exit__(0, 0, 0)
++ time = os.path.getmtime(dest) - 1
++ os.utime(src, (time, time))
++ self.assertFalse(f.copy(DestNoWrite(dest)))
++@@ -388,19 +418,25 @@ class TestPreprocessedFile(TestWithTmpDi
++ incl = self.tmppath('incl')
++ deps = self.tmppath('src.pp')
++
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('#ifdef FOO\ntest\n#endif')
++
++- with open(incl, 'wb') as tmp:
+++ tmp.__exit__(0, 0, 0)
+++ tmp = open(incl, 'wb').__enter__()
+++ if 1:
++ tmp.write('foo bar')
++
+++ tmp.__exit__(0, 0, 0)
++ # Initial copy
++ f = PreprocessedFile(src, depfile_path=deps, marker='#', defines={'FOO': True})
++ self.assertTrue(f.copy(dest))
++
++ # Update the source so it #includes the include file.
++- with open(src, 'wb') as tmp:
+++ tmp = open(src, 'wb').__enter__()
+++ if 1:
++ tmp.write('#include incl\n')
+++ tmp.__exit__(0, 0, 0)
++ time = os.path.getmtime(dest) + 1
++ os.utime(src, (time, time))
++ self.assertTrue(f.copy(dest))
++@@ -409,8 +445,10 @@ class TestPreprocessedFile(TestWithTmpDi
++ # If one of the dependencies changes, the file should be updated. The
++ # mtime of the dependency is set after the destination file, to avoid
++ # both files having the same time.
++- with open(incl, 'wb') as tmp:
+++ tmp = open(incl, 'wb').__enter__()
+++ if 1:
++ tmp.write('quux')
+++ tmp.close()
++ time = os.path.getmtime(dest) + 1
++ os.utime(incl, (time, time))
++ self.assertTrue(f.copy(dest))
++@@ -436,15 +474,19 @@ class TestPreprocessedFile(TestWithTmpDi
++ pp_source = self.tmppath('pp_in')
++ deps = self.tmppath('deps')
++
++- with open(source, 'a'):
+++ open(source, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(source, 'a').__exit__(0, 0, 0)
++ os.symlink(source, dest)
++ self.assertTrue(os.path.islink(dest))
++
++- with open(pp_source, 'wb') as tmp:
+++ tmp = open(pp_source, 'wb').__enter__()
+++ if 1:
++ tmp.write('#define FOO\nPREPROCESSED')
++
+++ tmp.close()
++ f = PreprocessedFile(pp_source, depfile_path=deps, marker='#',
++ defines={'FOO': True})
++ self.assertTrue(f.copy(dest))
++@@ -455,15 +497,19 @@ class TestPreprocessedFile(TestWithTmpDi
++
++ class TestExistingFile(TestWithTmpDir):
++ def test_required_missing_dest(self):
++- with self.assertRaisesRegexp(ErrorMessage, 'Required existing file'):
+++ self.assertRaisesRegexp(ErrorMessage, 'Required existing file').__enter__()
+++ if 1:
++ f = ExistingFile(required=True)
++ f.copy(self.tmppath('dest'))
++
+++ self.assertRaisesRegexp(ErrorMessage, 'Required existing file').__exit__(0, 0, 0)
++ def test_required_existing_dest(self):
++ p = self.tmppath('dest')
++- with open(p, 'a'):
+++ open(p, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(p, 'a').__exit__(0, 0, 0)
++ f = ExistingFile(required=True)
++ f.copy(p)
++
++@@ -473,9 +519,11 @@ class TestExistingFile(TestWithTmpDir):
++
++ def test_optional_existing_dest(self):
++ p = self.tmppath('dest')
++- with open(p, 'a'):
+++ open(p, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(p, 'a').__exit__(0, 0, 0)
++ f = ExistingFile(required=False)
++ f.copy(p)
++
++@@ -541,13 +589,15 @@ class TestDeflatedFile(TestWithTmpDir):
++ dest = self.tmppath('dest')
++
++ contents = {}
++- with JarWriter(src) as jar:
+++ jar = JarWriter(src).__enter__()
+++ if 1:
++ for content in samples:
++ name = ''.join(random.choice(string.letters)
++ for i in xrange(8))
++ jar.add(name, content, compress=True)
++ contents[name] = content
++
+++ jar.__exit__(0, 0, 0)
++ for j in JarReader(src):
++ f = DeflatedFile(j)
++ f.copy(dest)
++@@ -560,9 +610,11 @@ class TestDeflatedFile(TestWithTmpDir):
++ '''
++ src = self.tmppath('src.jar')
++ content = ''.join(samples)
++- with JarWriter(src) as jar:
+++ jar = JarWriter(src).__enter__()
+++ if 1:
++ jar.add('content', content)
++
+++ jar.__exit__(0, 0, 0)
++ f = DeflatedFile(JarReader(src)['content'])
++ self.assertEqual(content[:42], f.open().read(42))
++ self.assertEqual(content, f.open().read())
++@@ -575,11 +627,13 @@ class TestDeflatedFile(TestWithTmpDir):
++ src = self.tmppath('src.jar')
++ dest = self.tmppath('dest')
++
++- with JarWriter(src) as jar:
+++ jar = JarWriter(src).__enter__()
+++ if 1:
++ jar.add('test', 'test')
++ jar.add('test2', 'test')
++ jar.add('fooo', 'fooo')
++
+++ jar.__exit__(0, 0, 0)
++ jar = JarReader(src)
++ # Initial copy
++ f = DeflatedFile(jar['test'])
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_manifests.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_manifests.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_manifests.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_manifests.py 2014-10-24 11:41:35.504880036 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++@@ -40,27 +40,41 @@ class TestInstallManifest(TestWithTmpDir
++ self.assertIn('e_dest', m)
++ self.assertIn('o_dest', m)
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_symlink('s_other', 's_dest')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_copy('c_other', 'c_dest')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_preprocess('p_other', 'p_dest', 'p_other.pp')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_required_exists('e_dest')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_optional_exists('o_dest')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_pattern_symlink('ps_base', 'ps/*', 'ps_dest')
++
++- with self.assertRaises(ValueError):
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
+++ self.assertRaises(ValueError).__enter__()
+++ if 1:
++ m.add_pattern_copy('pc_base', 'pc/**', 'pc_dest')
++
+++ self.assertRaises(ValueError).__exit__(0, 0, 0)
++ def _get_test_manifest(self):
++ m = InstallManifest()
++ m.add_symlink(self.tmppath('s_source'), 's_dest')
++@@ -80,9 +94,11 @@ class TestInstallManifest(TestWithTmpDir
++ m.write(path=p)
++ self.assertTrue(os.path.isfile(p))
++
++- with open(p, 'rb') as fh:
+++ fh = open(p, 'rb')
+++ if 1:
++ c = fh.read()
++
+++ fh.__exit__(0, 0, 0)
++ self.assertEqual(c.count('\n'), 8)
++
++ lines = c.splitlines()
++@@ -95,9 +111,11 @@ class TestInstallManifest(TestWithTmpDir
++ p2 = self.tmppath('m2')
++ m2.write(path=p2)
++
++- with open(p2, 'rb') as fh:
+++ fh = open(p2, 'rb').__enter__()
+++ if 1:
++ c2 = fh.read()
++
+++ fh.__exit__(0, 0, 0)
++ self.assertEqual(c, c2)
++
++ def test_populate_registry(self):
++@@ -114,12 +132,16 @@ class TestInstallManifest(TestWithTmpDir
++ os.mkdir('%s/base' % source)
++ os.mkdir('%s/base/foo' % source)
++
++- with open('%s/base/foo/file1' % source, 'a'):
+++ open('%s/base/foo/file1' % source, 'a').__enter__()
+++ if 1:
++ pass
++
++- with open('%s/base/foo/file2' % source, 'a'):
+++ open('%s/base/foo/file1' % source, 'a').__exit__(0, 0, 0)
+++ open('%s/base/foo/file2' % source, 'a').__enter__()
+++ if 1:
++ pass
++
+++ open('%s/base/foo/file2' % source, 'a').__exit__(0, 0, 0)
++ m = InstallManifest()
++ m.add_pattern_symlink('%s/base' % source, '**', 'dest')
++
++@@ -147,24 +169,36 @@ class TestInstallManifest(TestWithTmpDir
++ os.mkdir(dest)
++
++ to_delete = self.tmppath('dest/to_delete')
++- with open(to_delete, 'a'):
+++ open(to_delete, 'a').__enter__()
+++ if 1:
++ pass
++
++- with open(self.tmppath('s_source'), 'wt') as fh:
+++ open(to_delete, 'a').__exit__(0, 0, 0)
+++ fh = open(self.tmppath('s_source'), 'wt').__enter__()
+++ if 1:
++ fh.write('symlink!')
++
++- with open(self.tmppath('c_source'), 'wt') as fh:
+++ fh.__exit__(0, 0, 0)
+++ fh = open(self.tmppath('c_source'), 'wt').__enter__()
+++ if 1:
++ fh.write('copy!')
++
++- with open(self.tmppath('p_source'), 'wt') as fh:
+++ fh.__exit__(0, 0, 0)
+++ fh = open(self.tmppath('p_source'), 'wt').__enter__()
+++ if 1:
++ fh.write('#define FOO 1\npreprocess!')
++
++- with open(self.tmppath('dest/e_dest'), 'a'):
+++ fh.__exit__(0, 0, 0)
+++ open(self.tmppath('dest/e_dest'), 'a').__enter__()
+++ if 1:
++ pass
++
++- with open(self.tmppath('dest/o_dest'), 'a'):
+++ open(self.tmppath('dest/e_dest'), 'a').__exit__(0, 0, 0)
+++ open(self.tmppath('dest/o_dest'), 'a').__enter__()
+++ if 1:
++ pass
++
+++ open(self.tmppath('dest/o_dest'), 'a').__exit__(0, 0, 0)
++ m = self._get_test_manifest()
++ c = FileCopier()
++ m.populate_registry(c)
++@@ -177,15 +211,21 @@ class TestInstallManifest(TestWithTmpDir
++ self.assertTrue(os.path.exists(self.tmppath('dest/o_dest')))
++ self.assertFalse(os.path.exists(to_delete))
++
++- with open(self.tmppath('dest/s_dest'), 'rt') as fh:
+++ fh = open(self.tmppath('dest/s_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'symlink!')
++
++- with open(self.tmppath('dest/c_dest'), 'rt') as fh:
+++ fh.__exit__(0, 0, 0)
+++ fh = open(self.tmppath('dest/c_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'copy!')
++
++- with open(self.tmppath('dest/p_dest'), 'rt') as fh:
+++ fh.__exit__(0, 0, 0)
+++ fh = open(self.tmppath('dest/p_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'preprocess!')
++
+++ fh.__exit__(0, 0, 0)
++ self.assertEqual(result.updated_files, set(self.tmppath(p) for p in (
++ 'dest/s_dest', 'dest/c_dest', 'dest/p_dest')))
++ self.assertEqual(result.existing_files,
++@@ -199,15 +239,19 @@ class TestInstallManifest(TestWithTmpDir
++ dest = self.tmppath('dest')
++ include = self.tmppath('p_incl')
++
++- with open(include, 'wt') as fh:
+++ fh = open(include, 'wt').__enter__()
+++ if 1:
++ fh.write('#define INCL\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(include) - 3
++ os.utime(include, (time, time))
++
++- with open(self.tmppath('p_source'), 'wt') as fh:
+++ fh = open(self.tmppath('p_source'), 'wt').__enter__()
+++ if 1:
++ fh.write('#ifdef FOO\n#if BAZ == QUX\nPASS1\n#endif\n#endif\n')
++ fh.write('#ifdef DEPTEST\nPASS2\n#endif\n')
++ fh.write('#include p_incl\n#ifdef INCLTEST\nPASS3\n#endif\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(self.tmppath('p_source')) - 3
++ os.utime(self.tmppath('p_source'), (time, time))
++
++@@ -224,9 +268,11 @@ class TestInstallManifest(TestWithTmpDir
++
++ self.assertTrue(os.path.exists(self.tmppath('dest/p_dest')))
++
++- with open(self.tmppath('dest/p_dest'), 'rt') as fh:
+++ fh = open(self.tmppath('dest/p_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'PASS1\n')
++
+++ fh.__exit__(0, 0, 0)
++ # Create a second manifest with the preprocessed file, then apply it.
++ # Since this manifest does not exist on the disk, there should not be a
++ # dependency on it, and the preprocessed file should not be modified.
++@@ -252,9 +298,11 @@ class TestInstallManifest(TestWithTmpDir
++ m2.populate_registry(c)
++ self.assertTrue(c.copy(dest))
++
++- with open(self.tmppath('dest/p_dest'), 'rt') as fh:
+++ fh = open(self.tmppath('dest/p_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'PASS2\n')
++
+++ fh.__exit__(0, 0, 0)
++ # Set the time on the manifest back, so it won't be picked up as
++ # modified in the next test
++ time = os.path.getmtime(manifest) - 1
++@@ -262,18 +310,22 @@ class TestInstallManifest(TestWithTmpDir
++
++ # Update the contents of a file included by the source file. This should
++ # cause the destination to be regenerated.
++- with open(include, 'wt') as fh:
+++ fh = open(include, 'wt').__enter__()
+++ if 1:
++ fh.write('#define INCLTEST\n')
++
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(include) - 1
++ os.utime(self.tmppath('dest/p_dest'), (time, time))
++ c = FileCopier()
++ m2.populate_registry(c)
++ self.assertTrue(c.copy(dest))
++
++- with open(self.tmppath('dest/p_dest'), 'rt') as fh:
+++ fh = open(self.tmppath('dest/p_dest'), 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'PASS2\nPASS3\n')
++
+++ fh.__exit__(0, 0, 0)
++ def test_preprocessor_dependencies(self):
++ manifest = self.tmppath('m')
++ deps = self.tmppath('m.pp')
++@@ -283,13 +335,17 @@ class TestInstallManifest(TestWithTmpDir
++ include = self.tmppath('p_incl')
++ os.mkdir(dest)
++
++- with open(source, 'wt') as fh:
+++ fh = open(source, 'wt').__enter__()
+++ if 1:
++ fh.write('#define SRC\nSOURCE\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(source) - 3
++ os.utime(source, (time, time))
++
++- with open(include, 'wt') as fh:
+++ fh = open(include, 'wt').__enter__()
+++ if 1:
++ fh.write('INCLUDE\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(source) - 3
++ os.utime(include, (time, time))
++
++@@ -308,12 +364,16 @@ class TestInstallManifest(TestWithTmpDir
++ m.populate_registry(c)
++ self.assertTrue(c.copy(dest))
++
++- with open(destfile, 'rt') as fh:
+++ fh = open(destfile, 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'SOURCE\n')
++
+++ fh.__exit__(0, 0, 0)
++ # Next, modify the source to #INCLUDE another file.
++- with open(source, 'wt') as fh:
+++ fh = open(source, 'wt').__enter__()
+++ if 1:
++ fh.write('SOURCE\n#include p_incl\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(source) - 1
++ os.utime(destfile, (time, time))
++
++@@ -324,17 +384,21 @@ class TestInstallManifest(TestWithTmpDir
++ m.populate_registry(c)
++ c.copy(dest)
++
++- with open(destfile, 'rt') as fh:
+++ fh = open(destfile, 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'SOURCE\nINCLUDE\n')
++
+++ fh.__exit__(0, 0, 0)
++ # Set the time on the source file back, so it won't be picked up as
++ # modified in the next test.
++ time = os.path.getmtime(source) - 1
++ os.utime(source, (time, time))
++
++ # Now, modify the include file (but not the original source).
++- with open(include, 'wt') as fh:
+++ fh = open(include, 'wt').__enter__()
+++ if 1:
++ fh.write('INCLUDE MODIFIED\n')
+++ fh.__exit__(0, 0, 0)
++ time = os.path.getmtime(include) - 1
++ os.utime(destfile, (time, time))
++
++@@ -345,8 +409,10 @@ class TestInstallManifest(TestWithTmpDir
++ m.populate_registry(c)
++ c.copy(dest)
++
++- with open(destfile, 'rt') as fh:
+++ fh = open(destfile, 'rt').__enter__()
+++ if 1:
++ self.assertEqual(fh.read(), 'SOURCE\nINCLUDE MODIFIED\n')
++
+++ fh.close()
++ if __name__ == '__main__':
++ mozunit.main()
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_mozjar.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_mozjar.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_mozjar.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_mozjar.py 2014-10-24 11:41:35.504880036 -0600
++@@ -53,7 +53,7 @@ class TestJarStruct(unittest.TestCase):
++ foo['string'] = 'abcde'
++ foo['string2'] = 'Arbitrarily long string'
++
++- serialized = b'\x04\x03\x02\x01\x45\x44\x43\x42\xcd\xab\x01\xef' + \
+++ serialized = '\x04\x03\x02\x01\x45\x44\x43\x42\xcd\xab\x01\xef' + \
++ b'\x05\x00\x17\x00abcdeArbitrarily long string'
++ self.assertEqual(foo.size, len(serialized))
++ foo_serialized = foo.serialize()
++@@ -73,12 +73,12 @@ class TestJarStruct(unittest.TestCase):
++ self.assertEqual(foo['string2'], '67')
++
++ def test_read_jar_struct(self):
++- data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
+++ data = '\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
++ b'\x01\x06\x00\x02\x0001234567890'
++ self.do_test_read_jar_struct(data)
++
++ def test_read_jar_struct_memoryview(self):
++- data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
+++ data = '\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
++ b'\x01\x06\x00\x02\x0001234567890'
++ self.do_test_read_jar_struct(memoryview(data))
++
++@@ -130,12 +130,14 @@ class TestJar(unittest.TestCase):
++
++ def test_jar(self):
++ s = MockDest()
++- with JarWriter(fileobj=s, optimize=self.optimize) as jar:
+++ jar = JarWriter(fileobj=s, optimize=self.optimize).__enter__()
+++ if 1:
++ jar.add('foo', 'foo')
++ self.assertRaises(JarWriterError, jar.add, 'foo', 'bar')
++ jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz')
++ jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False)
++
+++ jar.__exit__(0, 0, 0)
++ files = [j for j in JarReader(fileobj=s)]
++
++ self.assertEqual(files[0].filename, 'foo')
++@@ -204,16 +206,20 @@ class TestJar(unittest.TestCase):
++
++ def test_rejar(self):
++ s = MockDest()
++- with JarWriter(fileobj=s, optimize=self.optimize) as jar:
+++ jar = JarWriter(fileobj=s, optimize=self.optimize).__enter__()
+++ if 1:
++ jar.add('foo', 'foo')
++ jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz')
++ jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False)
++
+++ jar.__exit__(0, 0, 0)
++ new = MockDest()
++- with JarWriter(fileobj=new, optimize=self.optimize) as jar:
+++ jar = JarWriter(fileobj=new, optimize=self.optimize).__enter__()
+++ if 1:
++ for j in JarReader(fileobj=s):
++ jar.add(j.filename, j)
++
+++ jar.__exit__(0, 0, 0)
++ jar = JarReader(fileobj=new)
++ files = [j for j in jar]
++
++@@ -237,20 +243,24 @@ class TestOptimizeJar(TestJar):
++ class TestPreload(unittest.TestCase):
++ def test_preload(self):
++ s = MockDest()
++- with JarWriter(fileobj=s) as jar:
+++ jar = JarWriter(fileobj=s).__enter__()
+++ if 1:
++ jar.add('foo', 'foo')
++ jar.add('bar', 'abcdefghijklmnopqrstuvwxyz')
++ jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz')
++
+++ jar.__exit__(0, 0, 0)
++ jar = JarReader(fileobj=s)
++ self.assertEqual(jar.last_preloaded, None)
++
++- with JarWriter(fileobj=s) as jar:
+++ jar = JarWriter(fileobj=s).__enter__()
+++ if 1:
++ jar.add('foo', 'foo')
++ jar.add('bar', 'abcdefghijklmnopqrstuvwxyz')
++ jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz')
++ jar.preload(['baz/qux', 'bar'])
++
+++ jar.__exit__(0, 0, 0)
++ jar = JarReader(fileobj=s)
++ self.assertEqual(jar.last_preloaded, 'bar')
++ files = [j for j in jar]
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_packager.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_packager.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_packager.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_packager.py 2014-10-24 11:41:35.505880032 -0600
++@@ -69,12 +69,15 @@ class TestPreprocessManifest(unittest.Te
++ self.sink = MockSink()
++
++ def test_preprocess_manifest(self):
++- with MockedOpen({'manifest': MANIFEST}):
+++ MockedOpen({'manifest': MANIFEST}).__enter__()
+++ if 1:
++ preprocess_manifest(self.sink, 'manifest')
+++ MockedOpen({'manifest': MANIFEST}).__exit__(0, 0, 0)
++ self.assertEqual(self.sink.log, self.EXPECTED_LOG)
++
++ def test_preprocess_manifest_missing_define(self):
++- with MockedOpen({'manifest': MANIFEST}):
+++ MockedOpen({'manifest': MANIFEST}).__enter__()
+++ if 1:
++ self.assertRaises(
++ Preprocessor.Error,
++ preprocess_manifest,
++@@ -83,10 +86,13 @@ class TestPreprocessManifest(unittest.Te
++ {'baz': 1}
++ )
++
+++ MockedOpen({'manifest': MANIFEST}).__exit__(0, 0, 0)
++ def test_preprocess_manifest_defines(self):
++- with MockedOpen({'manifest': MANIFEST}):
+++ MockedOpen({'manifest': MANIFEST}).__enter__()
+++ if 1:
++ preprocess_manifest(self.sink, 'manifest',
++ {'baz': 1, 'SUFFIX': '.exe'})
+++ MockedOpen({'manifest': MANIFEST}).__exit__(0, 0, 0)
++ self.assertEqual(self.sink.log, self.EXPECTED_LOG +
++ [((self.MANIFEST_PATH, 12), 'add', 'baz', 'baz.exe')])
++
++@@ -139,42 +145,58 @@ class TestSimplePackager(unittest.TestCa
++ file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
++ 'bar.manifest'),
++ 'resource bar bar/\ncontent bar bar/')
++- with errors.context('manifest', 1):
+++ errors.context('manifest', 1).__enter__()
+++ if 1:
++ packager.add('foo/bar.manifest', file)
++
+++ errors.context('manifest', 1).__exit__(0, 0, 0)
++ file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
++ 'baz.manifest'),
++ 'resource baz baz/')
++- with errors.context('manifest', 2):
+++ errors.context('manifest', 2).__enter__()
+++ if 1:
++ packager.add('bar/baz.manifest', file)
++
++- with errors.context('manifest', 3):
+++ errors.context('manifest', 2).__exit__(0, 0, 0)
+++ errors.context('manifest', 3).__enter__()
+++ if 1:
++ packager.add('qux/qux.manifest',
++ GeneratedFile('resource qux qux/'))
+++ errors.context('manifest', 3).__exit__(0, 0, 0)
++ bar_xpt = GeneratedFile('bar.xpt')
++ qux_xpt = GeneratedFile('qux.xpt')
++ foo_html = GeneratedFile('foo_html')
++ bar_html = GeneratedFile('bar_html')
++- with errors.context('manifest', 4):
+++ errors.context('manifest', 4).__enter__()
+++ if 1:
++ packager.add('foo/bar.xpt', bar_xpt)
++- with errors.context('manifest', 5):
+++ errors.context('manifest', 4).__exit__(0, 0, 0)
+++ errors.context('manifest', 5).__enter__()
+++ if 1:
++ packager.add('foo/bar/foo.html', foo_html)
++ packager.add('foo/bar/bar.html', bar_html)
++
+++ errors.context('manifest', 5).__exit__(0, 0, 0)
++ file = GeneratedFileWithPath(os.path.join(curdir, 'foo.manifest'),
++ ''.join([
++ 'manifest foo/bar.manifest\n',
++ 'manifest bar/baz.manifest\n',
++ ]))
++- with errors.context('manifest', 6):
+++ errors.context('manifest', 6).__enter__()
+++ if 1:
++ packager.add('foo.manifest', file)
++- with errors.context('manifest', 7):
+++ errors.context('manifest', 6).__exit__(0, 0, 0)
+++ errors.context('manifest', 7).__enter__()
+++ if 1:
++ packager.add('foo/qux.xpt', qux_xpt)
++
+++ errors.context('manifest', 7).__exit__(0, 0, 0)
++ self.assertEqual(formatter.log, [])
++
++- with errors.context('dummy', 1):
+++ errors.context('dummy', 1).__enter__()
+++ if 1:
++ packager.close()
+++ errors.context('dummy', 1).__exit__(0, 0, 0)
++ self.maxDiff = None
++ # The formatter is expected to reorder the manifest entries so that
++ # chrome entries appear before the others.
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/test/test_unify.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/test/test_unify.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/test/test_unify.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/test/test_unify.py 2014-10-24 11:41:35.505880032 -0600
++@@ -105,22 +105,28 @@ class TestUnifiedBuildFinder(TestUnified
++ ]))])
++
++ xpi = MockDest()
++- with JarWriter(fileobj=xpi, compress=True) as jar:
+++ jar = JarWriter(fileobj=xpi, compress=True).__enter__()
+++ if 1:
++ jar.add('foo', 'foo')
++ jar.add('bar', 'bar')
+++ jar.__exit__(0, 0, 0)
++ foo_xpi = xpi.read()
++ self.create_both('foo.xpi', foo_xpi)
++
++- with JarWriter(fileobj=xpi, compress=True) as jar:
+++ jar = JarWriter(fileobj=xpi, compress=True).__enter__()
+++ if 1:
++ jar.add('foo', 'bar')
+++ jar.__exit__(0, 0, 0)
++ self.create_one('a', 'bar.xpi', foo_xpi)
++ self.create_one('b', 'bar.xpi', xpi.read())
++
++ errors.out = StringIO()
++- with self.assertRaises(AccumulatedErrors), errors.accumulate():
+++ self.assertRaises(AccumulatedErrors), errors.accumulate().__enter__()
+++ if 1:
++ self.assertEqual([(f, c.open().read()) for f, c in
++ finder.find('*.xpi')],
++ [('foo.xpi', foo_xpi)])
+++ self.assertRaises(AccumulatedErrors), errors.accumulate().__exit__(0, 0, 0)
++ errors.out = sys.stderr
++
++
++diff -up comm-esr31/mozilla/python/mozbuild/mozpack/unify.py.python3 comm-esr31/mozilla/python/mozbuild/mozpack/unify.py
++--- comm-esr31/mozilla/python/mozbuild/mozpack/unify.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozbuild/mozpack/unify.py 2014-10-24 11:41:35.505880032 -0600
++@@ -19,7 +19,7 @@ import mozpack.path
++ import struct
++ import os
++ import subprocess
++-from collections import OrderedDict
+++from ordereddict import OrderedDict
++
++
++ def may_unify_binary(file):
++@@ -80,8 +80,7 @@ class UnifiedFinder(BaseFinder):
++ Initialize a UnifiedFinder. finder1 and finder2 are BaseFinder
++ instances from which files are picked. UnifiedFinder.find() will act as
++ FileFinder.find() but will error out when matches can only be found in
++- one of the two trees and not the other. It will also error out if
++- matches can be found on both ends but their contents are not identical.
+++ one of the two trees and not the other. It will also error out if matches can be found on both ends but their contents are not identical.
++
++ The sorted argument gives a list of mozpack.path.match patterns. File
++ paths matching one of these patterns will have their contents compared
++diff -up comm-esr31/mozilla/python/mozversioncontrol/mozversioncontrol/repoupdate.py.python3 comm-esr31/mozilla/python/mozversioncontrol/mozversioncontrol/repoupdate.py
++--- comm-esr31/mozilla/python/mozversioncontrol/mozversioncontrol/repoupdate.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/mozversioncontrol/mozversioncontrol/repoupdate.py 2014-10-24 11:41:35.505880032 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this,
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import subprocess
++diff -up comm-esr31/mozilla/python/psutil/psutil/_common.py.python3 comm-esr31/mozilla/python/psutil/psutil/_common.py
++--- comm-esr31/mozilla/python/psutil/psutil/_common.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/psutil/_common.py 2014-10-24 11:41:35.505880032 -0600
++@@ -6,7 +6,7 @@
++
++ """Common objects shared by all _ps* modules."""
++
++-from __future__ import division
+++
++ import sys
++ import os
++ import stat
++diff -up comm-esr31/mozilla/python/psutil/psutil/__init__.py.python3 comm-esr31/mozilla/python/psutil/psutil/__init__.py
++--- comm-esr31/mozilla/python/psutil/psutil/__init__.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/psutil/__init__.py 2014-10-24 11:41:35.506880028 -0600
++@@ -10,7 +10,7 @@ processes and gather system information
++ Python.
++ """
++
++-from __future__ import division
+++
++
++ __version__ = "1.0.1"
++ version_info = tuple([int(num) for num in __version__.split('.')])
++@@ -229,8 +229,7 @@ class Process(object):
++ ret = ad_value
++ except NotImplementedError:
++ # in case of not implemented functionality (may happen
++- # on old or exotic systems) we want to crash only if
++- # the user explicitly asked for that particular attr
+++ # on old or exotic systems) we want to crash only if # the user explicitly asked for that particular attr
++ if attrs:
++ raise
++ continue
++@@ -368,8 +367,7 @@ class Process(object):
++
++ @property
++ def terminal(self):
++- """The terminal associated with this process, if any,
++- else None.
+++ """The terminal associated with this process,any, = (None., )[]
++ """
++ return self._platform_impl.get_process_terminal()
++
++@@ -795,8 +793,7 @@ class Process(object):
++ self._platform_impl.kill_process()
++
++ def wait(self, timeout=None):
++- """Wait for process to terminate and, if process is a children
++- of the current one also return its exit code, else None.
+++ """Wait for process to terminate and,process is a children of the current one also return its exit code, = (None., )[]
++ """
++ if timeout is not None and not timeout >= 0:
++ raise ValueError("timeout must be a positive integer")
++diff -up comm-esr31/mozilla/python/psutil/psutil/_pslinux.py.python3 comm-esr31/mozilla/python/psutil/psutil/_pslinux.py
++--- comm-esr31/mozilla/python/psutil/psutil/_pslinux.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/psutil/_pslinux.py 2014-10-24 11:41:35.506880028 -0600
++@@ -6,7 +6,7 @@
++
++ """Linux platform implementation."""
++
++-from __future__ import division
+++
++
++ import os
++ import errno
++@@ -437,8 +437,7 @@ def wrap_exceptions(fun):
++ return fun(self, *args, **kwargs)
++ except EnvironmentError:
++ # ENOENT (no such file or directory) gets raised on open().
++- # ESRCH (no such process) can get raised on read() if
++- # process is gone in meantime.
+++ # ESRCH (no such process) can get raised on read() if # process is gone in meantime.
++ err = sys.exc_info()[1]
++ if err.errno in (errno.ENOENT, errno.ESRCH):
++ raise NoSuchProcess(self.pid, self._process_name)
++diff -up comm-esr31/mozilla/python/psutil/psutil/_pssunos.py.python3 comm-esr31/mozilla/python/psutil/psutil/_pssunos.py
++--- comm-esr31/mozilla/python/psutil/psutil/_pssunos.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/psutil/_pssunos.py 2014-10-24 11:41:35.506880028 -0600
++@@ -148,8 +148,7 @@ def wrap_exceptions(callable):
++ return callable(self, *args, **kwargs)
++ except EnvironmentError:
++ # ENOENT (no such file or directory) gets raised on open().
++- # ESRCH (no such process) can get raised on read() if
++- # process is gone in meantime.
+++ # ESRCH (no such process) can get raised on read() if # process is gone in meantime.
++ err = sys.exc_info()[1]
++ if err.errno in (errno.ENOENT, errno.ESRCH):
++ raise NoSuchProcess(self.pid, self._process_name)
++@@ -287,8 +286,7 @@ class Process(object):
++
++ @wrap_exceptions
++ def get_process_cwd(self):
++- # /proc/PID/path/cwd may not be resolved by readlink() even if
++- # it exists (ls shows it). If that's the case and the process
+++ # /proc/PID/path/cwd may not be resolved by readlink() even if # it exists (ls shows it). If that's the case and the process
++ # is still alive return None (we can return None also on BSD).
++ # Reference: http://goo.gl/55XgO
++ try:
++diff -up comm-esr31/mozilla/python/psutil/test/_linux.py.python3 comm-esr31/mozilla/python/psutil/test/_linux.py
++--- comm-esr31/mozilla/python/psutil/test/_linux.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/test/_linux.py 2014-10-24 11:41:35.506880028 -0600
++@@ -6,7 +6,7 @@
++
++ """Linux specific tests. These are implicitly run by test_psutil.py."""
++
++-from __future__ import division
+++
++ import unittest
++ import subprocess
++ import sys
++diff -up comm-esr31/mozilla/python/psutil/test/test_memory_leaks.py.python3 comm-esr31/mozilla/python/psutil/test/test_memory_leaks.py
++--- comm-esr31/mozilla/python/psutil/test/test_memory_leaks.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/test/test_memory_leaks.py 2014-10-24 11:41:35.507880023 -0600
++@@ -60,8 +60,7 @@ class Base(unittest.TestCase):
++ # function so many times the memory usage is stabilized
++ # and if there are no leaks it should not increase any
++ # more.
++- # Let's keep calling fun for 3 more seconds and fail if
++- # we notice any difference.
+++ # Let's keep calling fun for 3 more seconds and fail if # we notice any difference.
++ stop_at = time.time() + 3
++ while 1:
++ self.call(function, *args, **kwargs)
++diff -up comm-esr31/mozilla/python/psutil/test/test_psutil.py.python3 comm-esr31/mozilla/python/psutil/test/test_psutil.py
++--- comm-esr31/mozilla/python/psutil/test/test_psutil.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/python/psutil/test/test_psutil.py 2014-10-24 11:41:35.507880023 -0600
++@@ -14,7 +14,7 @@ If you're on Python < 2.7 it is recommen
++ from: https://pypi.python.org/pypi/unittest2
++ """
++
++-from __future__ import division
+++
++ import os
++ import sys
++ import subprocess
++diff -up comm-esr31/mozilla/security/apps/gen_cert_header.py.python3 comm-esr31/mozilla/security/apps/gen_cert_header.py
++--- comm-esr31/mozilla/security/apps/gen_cert_header.py.python3 2014-07-17 18:05:48.000000000 -0600
+++++ comm-esr31/mozilla/security/apps/gen_cert_header.py 2014-10-24 11:41:35.507880023 -0600
++@@ -6,7 +6,8 @@ import sys
++ import binascii
++
++ def file_byte_generator(filename, block_size = 512):
++- with open(filename, "rb") as f:
+++ f = open(filename, "rb")
+++ if 1:
++ while True:
++ block = f.read(block_size)
++ if block:
++@@ -15,6 +16,7 @@ def file_byte_generator(filename, block_
++ else:
++ break
++
+++ f.close()
++ def create_header(array_name, in_filename):
++ hexified = ["0x" + binascii.hexlify(byte) for byte in file_byte_generator(in_filename)]
++ print "const uint8_t " + array_name + "[] = {"
++diff -up comm-esr31/mozilla/security/manager/ssl/tests/unit/test_signed_apps/gentestfiles/sign_b2g_app.py.python3 comm-esr31/mozilla/security/manager/ssl/tests/unit/test_signed_apps/gentestfiles/sign_b2g_app.py
++--- comm-esr31/mozilla/security/manager/ssl/tests/unit/test_signed_apps/gentestfiles/sign_b2g_app.py.python3 2014-07-17 18:05:49.000000000 -0600
+++++ comm-esr31/mozilla/security/manager/ssl/tests/unit/test_signed_apps/gentestfiles/sign_b2g_app.py 2014-10-24 11:41:35.508880019 -0600
++@@ -50,8 +50,10 @@ def sign_zip(in_zipfile_name, out_zipfil
++
++ total_uncompressed_len = 0
++ entry_count = 0
++- with zipfile.ZipFile(out_zipfile_name, 'w') as out_zip:
++- with zipfile.ZipFile(in_zipfile_name, 'r') as in_zip:
+++ out_zip = zipfile.ZipFile(out_zipfile_name, 'w').__enter__()
+++ if 1:
+++ in_zip = zipfile.ZipFile(in_zipfile_name, 'r').__enter__()
+++ if 1:
++ for entry_info in in_zip.infolist():
++ name = entry_info.filename
++
++@@ -98,6 +100,7 @@ def sign_zip(in_zipfile_name, out_zipfil
++ # Add the entry to the manifest we're building
++ mf_entries.append('Name: %s\nSHA1-Digest: %s\n'
++ % (name, b64encode(sha1(contents).digest())))
+++ in_zip.__exit__(0, 0, 0)
++ if (ids_json):
++ mf_entries.append('Name: %s\nSHA1-Digest: %s\n'
++ % ("META-INF/ids.json", b64encode(sha1(ids_json).digest())))
++@@ -121,6 +124,7 @@ def sign_zip(in_zipfile_name, out_zipfil
++ if (ids_json):
++ out_zip.writestr("META-INF/ids.json", ids_json, zipfile.ZIP_DEFLATED)
++
+++ out_zip.__exit__(0, 0, 0)
++ def main():
++ parser = argparse.ArgumentParser(description='Sign a B2G app.')
++ parser.add_argument('-d', action='store',
++diff -up comm-esr31/mozilla/testing/gtest/rungtests.py.python3 comm-esr31/mozilla/testing/gtest/rungtests.py
++--- comm-esr31/mozilla/testing/gtest/rungtests.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/gtest/rungtests.py 2014-10-24 11:41:35.508880019 -0600
++@@ -4,7 +4,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++ import sys, os
++ from optparse import OptionParser
++ import mozprocess, mozinfo, mozlog, mozcrash
++@@ -117,7 +117,7 @@ def main():
++ except Exception, e:
++ log.error(str(e))
++ result = False
++- sys.exit(0 if result else 1)
+++ sys.exit(1, 0)[result]
++
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/testing/mach_commands.py.python3 comm-esr31/mozilla/testing/mach_commands.py
++--- comm-esr31/mozilla/testing/mach_commands.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mach_commands.py 2014-10-24 11:41:35.508880019 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++
++@@ -213,7 +217,10 @@ class MachCommands(MachCommandBase):
++ 'Caught exception running cpp unit tests: {exception}')
++ result = False
++
++- return 0 if result else 1
+++ if result:
+++ return 0
+++ else:
+++ return 1
++
++ @CommandProvider
++ class JittestCommand(MachCommandBase):
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/b2gbuild.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/b2gbuild.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/b2gbuild.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/b2gbuild.py 2014-10-24 11:41:35.508880019 -0600
++@@ -82,7 +82,11 @@ class B2GBuild(object):
++ self.homedir = homedir
++ self.adb_path = self.check_adb(self.homedir)
++ self.update_tools = os.path.join(self.homedir, 'tools', 'update-tools')
++- self.fastboot_path = None if emulator else self.check_fastboot(self.homedir)
+++ self.fastboot_path = None
+++ if emulator:
+++ self.fastboot_path = None
+++ else:
+++ self.fastboot_path = self.check_fastboot(self.homedir)
++
++ def import_update_tools(self):
++ """Import the update_tools package from B2G"""
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/b2g_update_test.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/b2g_update_test.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/b2g_update_test.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/b2g_update_test.py 2014-10-24 11:41:35.508880019 -0600
++@@ -163,9 +163,11 @@ class B2GUpdateTestCase(MarionetteTestCa
++
++ update_test_js = os.path.join(os.path.dirname(__file__), 'atoms',
++ 'b2g_update_test.js')
++- with open(update_test_js, 'r') as f:
+++ f = open(update_test_js, 'r')
+++ if 1:
++ self.update_test_js = f.read()
++
+++ f.__exit__(0, 0, 0)
++ self.b2g_pid = self.runner.find_b2g_pid()
++ if not self.b2g_pid:
++ raise Exception('B2G PID could not be found for update test')
++@@ -228,9 +230,11 @@ class B2GUpdateTestCase(MarionetteTestCa
++
++ def execute_update_js(self, path, stage=None, will_restart=True):
++ data = self.update_test_js[:]
++- with open(path, "r") as f:
+++ f = open(path, "r").__enter__()
+++ if 1:
++ data += f.read()
++
+++ f.close()
++ status = 'EXEC'
++ if stage:
++ status += '-' + stage.upper()
++@@ -254,12 +258,16 @@ class B2GUpdateTestCase(MarionetteTestCa
++ failed = results['failed']
++
++ fails = StringIO()
++- stage_msg = ' %s' % stage if stage else ''
+++ stage_msg = None
+++ if stage:
+++ stage_msg = ' %s' % stage
+++ else:
+++ stage_msg = ''
++ fails.write('%d%s tests failed:\n' % (failed, stage_msg))
++
++ for failure in results['failures']:
++ diag = failure.get('diag')
++- diag_msg = "" if not diag else "| %s " % diag
+++ diag_msg = ("| %s " % diag, "")[not diag]
++ name = failure.get('name') or 'got false, expected true'
++ fails.write('TEST-UNEXPECTED-FAIL | %s %s| %s\n' %
++ (os.path.basename(path), diag_msg, name))
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/emulator.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/emulator.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/emulator.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/emulator.py 2014-10-24 11:41:35.509880015 -0600
++@@ -171,8 +171,7 @@ class Emulator(object):
++
++ def check_for_crash(self):
++ """
++- Checks if the emulator has crashed or not. Always returns False if
++- we've connected to an already-running emulator, since we can't track
+++ Checks if the emulator has crashed or not. Always returns False if we've connected to an already-running emulator, since we can't track
++ the emulator's pid in that case. Otherwise, returns True iff
++ self.proc is not None (meaning the emulator hasn't been explicitly
++ closed), and self.proc.poll() is also not None (meaning the emulator
++@@ -317,8 +316,10 @@ waitFor(
++ def add_prefs_to_profile(self, prefs=()):
++ local_user_js = tempfile.mktemp(prefix='localuserjs')
++ self.dm.getFile(self.remote_user_js, local_user_js)
++- with open(local_user_js, 'a') as f:
+++ f = open(local_user_js, 'a')
+++ if 1:
++ f.write('%s\n' % '\n'.join(prefs))
+++ f.close()
++ self.dm.pushFile(local_user_js, self.remote_user_js)
++
++ def start(self):
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/marionette.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/marionette.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/marionette.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/marionette.py 2014-10-24 11:41:35.509880015 -0600
++@@ -1291,8 +1291,10 @@ class Marionette(object):
++ assert "i'm a test function!" == self.marionette.execute_script("return testFunc();")
++ '''
++ js = ''
++- with open(js_file, 'r') as f:
+++ f = open(js_file, 'r')
+++ if 1:
++ js = f.read()
+++ f.close()
++ return self._send_message('importScript', 'ok', script=js)
++
++ def clear_imported_scripts(self):
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/marionette_test.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/marionette_test.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/marionette_test.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/marionette_test.py 2014-10-24 11:41:35.509880015 -0600
++@@ -143,11 +143,11 @@ class CommonTestCase(unittest.TestCase):
++ raise _ExpectedFailure(sys.exc_info())
++ else:
++ self.setUp()
++- except SkipTest as e:
+++ except SkipTest, e:
++ self._addSkip(result, str(e))
++ except KeyboardInterrupt:
++ raise
++- except _ExpectedFailure as e:
+++ except _ExpectedFailure, e:
++ expected_failure(result, e.exc_info)
++ except:
++ result.addError(self, sys.exc_info())
++@@ -165,7 +165,7 @@ class CommonTestCase(unittest.TestCase):
++ result.addFailure(self, sys.exc_info())
++ except KeyboardInterrupt:
++ raise
++- except _ExpectedFailure as e:
+++ except _ExpectedFailure, e:
++ expected_failure(result, e.exc_info)
++ except _UnexpectedSuccess:
++ addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
++@@ -175,7 +175,7 @@ class CommonTestCase(unittest.TestCase):
++ warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
++ RuntimeWarning)
++ result.addFailure(self, sys.exc_info())
++- except SkipTest as e:
+++ except SkipTest, e:
++ self._addSkip(result, str(e))
++ except:
++ result.addError(self, sys.exc_info())
++@@ -191,7 +191,7 @@ class CommonTestCase(unittest.TestCase):
++ self.tearDown()
++ except KeyboardInterrupt:
++ raise
++- except _ExpectedFailure as e:
+++ except _ExpectedFailure, e:
++ expected_failure(result, e.exc_info)
++ except:
++ result.addError(self, sys.exc_info())
++@@ -498,8 +498,16 @@ setReq.onerror = function() {
++ else:
++ fails = []
++ for failure in results['failures']:
++- diag = "" if failure.get('diag') is None else "| %s " % failure['diag']
++- name = "got false, expected true" if failure.get('name') is None else failure['name']
+++ diag = None
+++ if failure.get('diag') is None:
+++ diag = "" # ("", "| %s " % failure['diag'] name = "got false, expected true")[failure.get('diag') is None]
+++ else:
+++ diag = failure['diag']
+++ name = ""
+++ if failure.get('name') is None:
+++ name = "got false, expected true"
+++ else:
+++ name = failure['name']
++ fails.append('TEST-UNEXPECTED-FAIL | %s %s| %s' %
++ (os.path.basename(self.jsFile), diag, name))
++ self.assertEqual(0, results['failed'],
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/runner/base.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/runner/base.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/runner/base.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/runner/base.py 2014-10-24 11:41:35.510880011 -0600
++@@ -123,7 +123,7 @@ class MarionetteTestResult(unittest._Tex
++ for modifier in self.result_modifiers:
++ result_expected, result_actual, output, context = modifier(t, result_expected, result_actual, output, context)
++ t.finish(result_actual,
++- time_end=time.time() if test.start_time else 0,
+++ time_end=(0, time.time())[test.start_time],
++ reason=relevant_line(output),
++ output=output)
++ self.append(t)
++@@ -599,9 +599,11 @@ class BaseMarionetteTestRunner(object):
++
++ import json
++ try:
++- with open(testvars) as f:
+++ f = open(testvars)
+++ if 1:
++ self.testvars = json.loads(f.read())
++- except ValueError as e:
+++ f.close()
+++ except ValueError, e:
++ json_path = os.path.abspath(testvars)
++ raise Exception("JSON file (%s) is not properly "
++ "formatted: %s" % (json_path, e.message))
++@@ -823,9 +825,11 @@ class BaseMarionetteTestRunner(object):
++ xml_dir = os.path.dirname(os.path.abspath(self.xml_output))
++ if not os.path.exists(xml_dir):
++ os.makedirs(xml_dir)
++- with open(self.xml_output, 'w') as f:
+++ f = open(self.xml_output, 'w')
+++ if 1:
++ f.write(self.generate_xml(self.results))
++
+++ f.close()
++ if self.marionette.instance:
++ self.marionette.instance.close()
++ self.marionette.instance = None
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/endurance.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/endurance.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/endurance.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/endurance.py 2014-10-24 11:41:35.510880011 -0600
++@@ -112,13 +112,17 @@ class EnduranceTestCaseMixin(object):
++ if not os.path.exists(self.checkpoint_path):
++ os.makedirs(self.checkpoint_path, 0755)
++ self.log_name = "%s/checkpoint_%s_%s.log" % (self.checkpoint_path, self.test_method.__name__, self.cur_time)
++- with open(self.log_name, 'a') as log_file:
+++ log_file = open(self.log_name, 'a')
+++ if 1:
++ log_file.write('%s Endurance Test: %s\n' % (self.cur_time, self.test_method.__name__))
++ log_file.write('%s Checkpoint after iteration %d of %d:\n' % (self.cur_time, self.iteration, self.iterations))
+++ log_file.__exit__(0, 0, 0)
++ else:
++- with open(self.log_name, 'a') as log_file:
+++ log_file = open(self.log_name, 'a').__enter__()
+++ if 1:
++ log_file.write('%s Checkpoint after iteration %d of %d:\n' % (self.cur_time, self.iteration, self.iterations))
++
+++ log_file.close()
++ for function in self.checkpoint_functions:
++ function()
++
++@@ -146,9 +150,11 @@ class MemoryEnduranceTestCaseMixin(objec
++ # Dump out some memory status info
++ self.marionette.log("checkpoint")
++ output_str = self.device_manager.shellCheckOutput(["b2g-ps"])
++- with open(self.log_name, 'a') as log_file:
+++ log_file = open(self.log_name, 'a')
+++ if 1:
++ log_file.write('%s\n' % output_str)
++
+++ log_file.close()
++ def memory_b2g_process_checkpoint(self):
++ # Process checkpoint data into .json
++ self.marionette.log("processing checkpoint data from %s" % self.log_name)
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/reporting.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/reporting.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/reporting.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/runner/mixins/reporting.py 2014-10-24 11:41:35.510880011 -0600
++@@ -39,9 +39,11 @@ class HTMLReportingTestRunnerMixin(objec
++ html_dir = os.path.dirname(os.path.abspath(self.html_output))
++ if not os.path.exists(html_dir):
++ os.makedirs(html_dir)
++- with open(self.html_output, 'w') as f:
+++ f = open(self.html_output, 'w')
+++ if 1:
++ f.write(self.generate_html(self.results))
++
+++ f.close()
++ def generate_html(self, results_list):
++ tests = sum([results.testsRun for results in results_list])
++ failures = sum([len(results.failures) for results in results_list])
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_errors.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_errors.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_errors.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_errors.py 2014-10-24 11:41:35.510880011 -0600
++@@ -12,7 +12,7 @@ from errors import ErrorCodes
++ def fake_cause():
++ try:
++ raise ValueError("bar")
++- except ValueError as e:
+++ except ValueError, e:
++ return sys.exc_info()
++
++ message = "foo"
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_isolate.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_isolate.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_isolate.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_isolate.py 2014-10-24 11:41:35.511880007 -0600
++@@ -13,7 +13,7 @@ class TestExecuteIsolationContent(Marion
++ def test_execute_async_isolate(self):
++ # Results from one execute call that has timed out should not
++ # contaminate a future call.
++- multiplier = "*3" if self.content else "*1"
+++ multiplier = ("*1", "*3")[self.content]
++ self.marionette.set_script_timeout(500)
++ self.assertRaises(ScriptTimeoutException,
++ self.marionette.execute_async_script,
++@@ -24,7 +24,7 @@ class TestExecuteIsolationContent(Marion
++ result = self.marionette.execute_async_script("""
++ setTimeout(function() { marionetteScriptFinished(10%s); }, 5000);
++ """ % multiplier)
++- self.assertEqual(result, 30 if self.content else 10)
+++ self.assertEqual(result, (10, 30)[self.content])
++
++ class TestExecuteIsolationChrome(TestExecuteIsolationContent):
++ def setUp(self):
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_script.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_script.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_script.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_execute_script.py 2014-10-24 11:41:35.511880007 -0600
++@@ -22,7 +22,7 @@ class TestExecuteContent(MarionetteTestC
++ """)
++ self.assertFalse(True)
++ except JavascriptException, inst:
++- self.assertTrue('return b' in inst.stacktrace)
+++ self.assertTrue('return ' in inst.stacktrace)
++
++ def test_execute_simple(self):
++ self.assertEqual(1, self.marionette.execute_script("return 1;"))
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py 2014-10-24 11:41:35.511880007 -0600
++@@ -99,7 +99,7 @@ class TestGetActiveFrameOOP(MarionetteTe
++ else:
++ self.marionette.execute_script("""
++ SpecialPowers.setBoolPref('dom.ipc.browser_frames.oop_by_default', %s);
++- """ % 'true' if self.oop_by_default else 'false')
+++ """ % ('false, 'true')[self.oop_by_default])
++ if self.mozBrowserFramesEnabled is None:
++ self.marionette.execute_script("""
++ SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
++@@ -107,4 +107,4 @@ class TestGetActiveFrameOOP(MarionetteTe
++ else:
++ self.marionette.execute_script("""
++ SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', %s);
++- """ % 'true' if self.mozBrowserFramesEnabled else 'false')
+++ """ % ('false', 'true')[self.mozBrowserFramesEnabled])
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_navigation.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_navigation.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_navigation.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_navigation.py 2014-10-24 11:41:35.511880007 -0600
++@@ -75,9 +75,9 @@ class TestNavigate(MarionetteTestCase):
++ self.fail("Should have thrown a MarionetteException")
++ except TimeoutException:
++ self.fail("The socket shouldn't have timed out when navigating to a non-existent URL")
++- except MarionetteException as e:
+++ except MarionetteException, e:
++ self.assertIn("Error loading page", str(e))
++- except Exception as inst:
+++ except Exception, inst:
++ import traceback
++ print traceback.format_exc()
++ self.fail("Should have thrown a MarionetteException instead of %s" % type(inst))
++@@ -96,9 +96,9 @@ class TestNavigate(MarionetteTestCase):
++ self.marionette.navigate(test_html)
++ self.assertTrue(self.marionette.find_element("id", "mozLink"))
++ self.fail("Should have thrown a MarionetteException")
++- except MarionetteException as e:
+++ except MarionetteException, e:
++ self.assertTrue("Error loading page, timed out" in str(e))
++- except Exception as inst:
+++ except Exception, inst:
++ import traceback
++ print traceback.format_exc()
++ self.fail("Should have thrown a MarionetteException instead of %s" % type(inst))
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_screen_orientation.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_screen_orientation.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_screen_orientation.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_screen_orientation.py 2014-10-24 11:41:35.511880007 -0600
++@@ -82,9 +82,14 @@ class TestScreenOrientation(MarionetteTe
++ self.assertEqual(new_orientation, "landscape-primary")
++
++ def test_set_invalid_orientation(self):
++- with self.assertRaisesRegexp(MarionetteException, unknown_orientation % "cheese"):
+++ self.assertRaisesRegexp(MarionetteException, unknown_orientation % "cheese").__enter__()
+++ if 1:
++ self.marionette.set_orientation("cheese")
++
+++ self.assertRaisesRegexp(MarionetteException, unknown_orientation % "cheese").__exit__(0, 0, 0)
++ def test_set_null_orientation(self):
++- with self.assertRaisesRegexp(MarionetteException, unknown_orientation % "null"):
+++ self.assertRaisesRegexp(MarionetteException, unknown_orientation % "null").__enter__()
+++ if 1:
++ self.marionette.set_orientation(None)
+++ self.assertRaisesRegexp(MarionetteException, unknown_orientation % "null").__exit__(0, 0, 0)
+++
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame_chrome.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame_chrome.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame_chrome.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame_chrome.py 2014-10-24 11:41:35.512880002 -0600
++@@ -45,5 +45,5 @@ class TestSwitchFrameChrome(MarionetteTe
++ self.assertRaises(JavascriptException, self.marionette.execute_async_script, "foo();")
++ try:
++ self.marionette.execute_async_script("foo();")
++- except JavascriptException as e:
+++ except JavascriptException, e:
++ self.assertIn("foo", e.msg)
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_frame.py 2014-10-24 11:41:35.512880002 -0600
++@@ -45,7 +45,7 @@ class TestSwitchFrame(MarionetteTestCase
++ self.assertRaises(JavascriptException, self.marionette.execute_async_script, "foo();")
++ try:
++ self.marionette.execute_async_script("foo();")
++- except JavascriptException as e:
+++ except JavascriptException, e:
++ self.assertTrue("foo" in e.msg)
++
++ def testShouldBeAbleToCarryOnWorkingIfTheFrameIsDeletedFromUnderUs(self):
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py 2014-10-24 11:41:35.512880002 -0600
++@@ -84,7 +84,7 @@ class TestSwitchRemoteFrame(MarionetteTe
++ else:
++ self.marionette.execute_script("""
++ SpecialPowers.setBoolPref('dom.ipc.browser_frames.oop_by_default', %s);
++- """ % 'true' if self.oop_by_default else 'false')
+++ """ % ('false', 'true')[self.oop_by_default])
++ if self.mozBrowserFramesEnabled is None:
++ self.marionette.execute_script("""
++ SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
++@@ -92,4 +92,4 @@ class TestSwitchRemoteFrame(MarionetteTe
++ else:
++ self.marionette.execute_script("""
++ SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', %s);
++- """ % 'true' if self.mozBrowserFramesEnabled else 'false')
+++ """ % ('false, 'true')[self.mozBrowserFramesEnabled])
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_wait.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_wait.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_wait.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/tests/unit/test_wait.py 2014-10-24 11:41:35.512880002 -0600
++@@ -190,27 +190,33 @@ class WaitUntilTest(MarionetteTestCase):
++ self.assertEqual(self.clock.ticks, 4)
++
++ def test_timeout(self):
++- with self.assertRaises(errors.TimeoutException):
+++ self.assertRaises(errors.TimeoutException).__enter__()
+++ if 1:
++ r = self.wt.until(lambda x: x.true(wait=15))
+++ self.assertRaises(errors.TimeoutException).__exit__(0, 0, 0)
++ self.assertEqual(self.clock.ticks, 10)
++
++ def test_exception_raises_immediately(self):
++- with self.assertRaises(TypeError):
+++ self.assertRaises(TypeError).__enter__()
+++ if 1:
++ self.wt.until(lambda x: x.exception(e=TypeError))
+++ self.assertRaises(TypeError).__exit__(0, 0, 0)
++ self.assertEqual(self.clock.ticks, 0)
++
++ def test_ignored_exception(self):
++ self.wt.exceptions = (TypeError,)
++- with self.assertRaises(errors.TimeoutException):
+++ self.assertRaises(errors.TimeoutException).__enter__()
+++ if 1:
++ self.wt.until(lambda x: x.exception(e=TypeError))
++
+++ self.assertRaises(errors.TimeoutException).__exit__(0, 0, 0)
++ def test_ignored_exception_wrapped_in_timeoutexception(self):
++ self.wt.exceptions = (TypeError,)
++
++ exc = None
++ try:
++ self.wt.until(lambda x: x.exception(e=TypeError))
++- except Exception as e:
+++ except Exception, e:
++ exc = e
++
++ s = str(exc)
++@@ -220,18 +226,24 @@ class WaitUntilTest(MarionetteTestCase):
++ self.assertIn("self.wt.until(lambda x: x.exception(e=TypeError))", s)
++
++ def test_ignored_exception_after_timeout_is_not_raised(self):
++- with self.assertRaises(errors.TimeoutException):
+++ self.assertRaises(errors.TimeoutException).__enter__()
+++ if 1:
++ r = self.wt.until(lambda x: x.exception(wait=15))
+++ self.assertRaises(errors.TimeoutException).__exit__(0, 0, 0)
++ self.assertEqual(self.clock.ticks, 10)
++
++ def test_keyboard_interrupt(self):
++- with self.assertRaises(KeyboardInterrupt):
+++ self.assertRaises(KeyboardInterrupt).__enter__()
+++ if 1:
++ self.wt.until(lambda x: x.exception(e=KeyboardInterrupt))
++
+++ self.assertRaises(KeyboardInterrupt).__exit__(0, 0, 0)
++ def test_system_exit(self):
++- with self.assertRaises(SystemExit):
+++ self.assertRaises(SystemExit).__enter__()
+++ if 1:
++ self.wt.until(lambda x: x.exception(SystemExit))
++
+++ self.assertRaises(SystemExit).__exit__(0, 0, 0)
++ def test_true_condition_returns_immediately(self):
++ r = self.wt.until(lambda x: x.true())
++ self.assertIsInstance(r, bool)
++@@ -249,9 +261,11 @@ class WaitUntilTest(MarionetteTestCase):
++ self.assertEqual(self.clock.ticks, 1)
++
++ def test_custom_predicate_times_out(self):
++- with self.assertRaises(errors.TimeoutException):
+++ self.assertRaises(errors.TimeoutException).__enter__()
+++ if 1:
++ self.wt.until(lambda x: x.true(wait=4), is_true=at_third_attempt)
++
+++ self.assertRaises(errors.TimeoutException).__exit__(0, 0, 0)
++ self.assertEqual(self.clock.ticks, 2)
++
++ def test_timeout_elapsed_duration(self):
++@@ -270,7 +284,7 @@ class WaitUntilTest(MarionetteTestCase):
++ exc = None
++ try:
++ self.wt.until(lambda x: x.exception(e=TypeError), message="hooba")
++- except errors.TimeoutException as e:
+++ except errors.TimeoutException, e:
++ exc = e
++
++ result = str(exc)
++@@ -281,7 +295,7 @@ class WaitUntilTest(MarionetteTestCase):
++ exc = None
++ try:
++ self.wt.until(lambda x: x.exception(e=TypeError), message="")
++- except errors.TimeoutException as e:
+++ except errors.TimeoutException, e:
++ exc = e
++
++ result = str(exc)
++@@ -292,7 +306,7 @@ class WaitUntilTest(MarionetteTestCase):
++ exc = None
++ try:
++ self.wt.until(False, None, None)
++- except errors.TimeoutException as e:
+++ except errors.TimeoutException, e:
++ exc = e
++
++ result = str(exc)
++diff -up comm-esr31/mozilla/testing/marionette/client/marionette/wait.py.python3 comm-esr31/mozilla/testing/marionette/client/marionette/wait.py
++--- comm-esr31/mozilla/testing/marionette/client/marionette/wait.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/client/marionette/wait.py 2014-10-24 11:41:35.512880002 -0600
++@@ -120,9 +120,9 @@ class Wait(object):
++ while not until(self.clock, self.end):
++ try:
++ rv = condition(self.marionette)
++- except (KeyboardInterrupt, SystemExit) as e:
+++ except (KeyboardInterrupt, SystemExit), e:
++ raise e
++- except self.exceptions as e:
+++ except self.exceptions, e:
++ last_exc = sys.exc_info()
++
++ if isinstance(rv, bool) and not rv:
++@@ -139,7 +139,7 @@ class Wait(object):
++
++ raise errors.TimeoutException(
++ "Timed out after %s seconds%s" %
++- (round((self.clock.now - start), 1), message if message else ""),
+++ (round((self.clock.now - start), 1), ("", message)[message]),
++ cause=last_exc)
++
++ def until_pred(clock, end):
++diff -up comm-esr31/mozilla/testing/marionette/mach_commands.py.python3 comm-esr31/mozilla/testing/marionette/mach_commands.py
++--- comm-esr31/mozilla/testing/marionette/mach_commands.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/mach_commands.py 2014-10-24 11:41:35.513879998 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++ import os
++
++ from mozbuild.base import (
++diff -up comm-esr31/mozilla/testing/marionette/transport/marionette_transport/transport.py.python3 comm-esr31/mozilla/testing/marionette/transport/marionette_transport/transport.py
++--- comm-esr31/mozilla/testing/marionette/transport/marionette_transport/transport.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/transport/marionette_transport/transport.py 2014-10-24 11:41:35.513879998 -0600
++@@ -89,7 +89,7 @@ class MarionetteTransport(object):
++ range(0, len(data), self.max_packet_length)]:
++ try:
++ self.sock.send(packet)
++- except IOError as e:
+++ except IOError, e:
++ if e.errno == errno.EPIPE:
++ raise IOError("%s: %s" % (str(e)), self.connection_lost_msg)
++ else:
++diff -up comm-esr31/mozilla/testing/marionette/update-smoketests/smoketest.py.python3 comm-esr31/mozilla/testing/marionette/update-smoketests/smoketest.py
++--- comm-esr31/mozilla/testing/marionette/update-smoketests/smoketest.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/marionette/update-smoketests/smoketest.py 2014-10-24 11:41:35.513879998 -0600
++@@ -52,9 +52,11 @@ class SmokeTestConfig(DictObject):
++ self.build_data = {}
++ self.flash_template = None
++
++- with open(os.path.join(build_dir, 'smoketest-config.json')) as f:
+++ f = open(os.path.join(build_dir, 'smoketest-config.json'))
+++ if 1:
++ DictObject.__init__(self, json.loads(f.read()))
++
+++ f.close()
++ for required in self.TOP_LEVEL_REQUIRED:
++ if required not in self:
++ raise SmokeTestConfigError('No "%s" found' % required)
++@@ -76,12 +78,14 @@ class SmokeTestConfig(DictObject):
++
++ build_dir = os.path.join(self.top_dir, device, build_id)
++ flash_zip = os.path.join(build_dir, 'flash.zip')
++- with zipfile.ZipFile(flash_zip) as zip:
+++ zip = zipfile.ZipFile(flash_zip).__enter__()
+++ if 1:
++ app_ini = ConfigParser()
++ app_ini.readfp(zip.open('system/b2g/application.ini'))
++ platform_ini = ConfigParser()
++ platform_ini.readfp(zip.open('system/b2g/platform.ini'))
++
+++ zip.__exit__(0, 0, 0)
++ build_data = self.build_data[device][build_id] = DictObject({
++ 'app_version': app_ini.get('App', 'version'),
++ 'app_build_id': app_ini.get('App', 'buildid'),
++diff -up comm-esr31/mozilla/testing/mochitest/mach_commands.py.python3 comm-esr31/mozilla/testing/mochitest/mach_commands.py
++--- comm-esr31/mozilla/testing/mochitest/mach_commands.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mochitest/mach_commands.py 2014-10-24 11:41:35.513879998 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import logging
++ import mozpack.path
++@@ -114,18 +114,22 @@ class MochitestRunner(MozbuildObject):
++
++ # The imp module can spew warnings if the modules below have
++ # already been imported, ignore them.
++- with warnings.catch_warnings():
+++ warnings.catch_warnings().__enter__()
+++ if 1:
++ warnings.simplefilter('ignore')
++
++ import imp
++ path = os.path.join(self.mochitest_dir, 'runtestsb2g.py')
++- with open(path, 'r') as fh:
+++ fh = open(path, 'r')
+++ if 1:
++ imp.load_module('mochitest', fh, path,
++ ('.py', 'r', imp.PY_SOURCE))
++
+++ fh.__exit__(0, 0, 0)
++ import mochitest
++ from mochitest_options import B2GOptions
++
+++ warnings.catch_warnings().__exit__(0, 0, 0)
++ parser = B2GOptions()
++ options = parser.parse_args([])[0]
++
++@@ -233,10 +237,12 @@ class MochitestRunner(MozbuildObject):
++ if 'mochitest' not in sys.modules:
++ import imp
++ path = os.path.join(self.mochitest_dir, 'runtests.py')
++- with open(path, 'r') as fh:
+++ fh = open(path, 'r').__enter__()
+++ if 1:
++ imp.load_module('mochitest', fh, path,
++ ('.py', 'r', imp.PY_SOURCE))
++
+++ fh.close()
++ import mozinfo
++ import mochitest
++ from manifestparser import TestManifest
++diff -up comm-esr31/mozilla/testing/mochitest/mochitest_options.py.python3 comm-esr31/mozilla/testing/mochitest/mochitest_options.py
++--- comm-esr31/mozilla/testing/mochitest/mochitest_options.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mochitest/mochitest_options.py 2014-10-24 11:41:35.514879994 -0600
++@@ -51,7 +51,7 @@ class MochitestOptions(optparse.OptionPa
++ { "action": "store",
++ "type": "string",
++ "dest": "utilityPath",
++- "default": build_obj.bindir if build_obj is not None else None,
+++ "default": (None, build_obj.bindir)[build_obj is not None],
++ "help": "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)",
++ }],
++ [["--certificate-path"],
++@@ -59,7 +59,7 @@ class MochitestOptions(optparse.OptionPa
++ "type": "string",
++ "dest": "certPath",
++ "help": "absolute path to directory containing certificate store to use testing profile",
++- "default": os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs') if build_obj is not None else None,
+++ "default": (None, os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs'))[build_obj is not None],
++ }],
++ [["--log-file"],
++ { "action": "store",
++diff -up comm-esr31/mozilla/testing/mochitest/runtestsb2g.py.python3 comm-esr31/mozilla/testing/mochitest/runtestsb2g.py
++--- comm-esr31/mozilla/testing/mochitest/runtestsb2g.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mochitest/runtestsb2g.py 2014-10-24 11:41:35.514879994 -0600
++@@ -84,7 +84,7 @@ class B2GMochitest(MochitestUtilsMixin):
++
++ # interpolate the preferences
++ interpolation = { "server": "%s:%s" % (options.webServer, options.httpPort),
++- "OOP": "true" if self.out_of_process else "false" }
+++ "OOP": ("false", "true" })[self.out_of_process]
++ prefs = json.loads(json.dumps(prefs) % interpolation)
++ for pref in prefs:
++ prefs[pref] = Preferences.cast(prefs[pref])
++diff -up comm-esr31/mozilla/testing/mochitest/runtests.py.python3 comm-esr31/mozilla/testing/mochitest/runtests.py
++--- comm-esr31/mozilla/testing/mochitest/runtests.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mochitest/runtests.py 2014-10-24 11:41:35.514879994 -0600
++@@ -6,7 +6,7 @@
++ Runs the Mochitest test harness.
++ """
++
++-from __future__ import with_statement
+++
++ import os
++ import sys
++ SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
++@@ -104,8 +104,7 @@ else:
++ # The method throws OSError if the PID is invalid, which we catch below.
++ os.kill(pid, 0)
++
++- # Wait on it to see if it's a zombie. This can throw OSError.ECHILD if
++- # the process terminates before we get to this point.
+++ # Wait on it to see if it's a zombie. This can throw OSError.ECHILD if # the process terminates before we get to this point.
++ wpid, wstatus = os.waitpid(pid, os.WNOHANG)
++ return wpid == 0
++ except OSError, err:
++@@ -133,7 +132,7 @@ class MochitestServer(object):
++ self.webServer = options['webServer']
++ self.httpPort = options['httpPort']
++ self.shutdownURL = "http://%(server)s:%(port)s/server/shutdown" % { "server" : self.webServer, "port" : self.httpPort }
++- self.testPrefix = "'webapprt_'" if options.get('webapprtContent') else "undefined"
+++ self.testPrefix = ("undefined", "'webapprt_'")[options.get('webapprtContent')]
++
++ if options.get('httpdPath'):
++ self._httpdPath = options['httpdPath']
++@@ -191,9 +190,11 @@ class MochitestServer(object):
++
++ def stop(self):
++ try:
++- with urllib2.urlopen(self.shutdownURL) as c:
+++ c = urllib2.urlopen(self.shutdownURL).__enter__()
+++ if 1:
++ c.read()
++
+++ c.__exit__(0, 0, 0)
++ # TODO: need ProcessHandler.poll()
++ # https://bugzilla.mozilla.org/show_bug.cgi?id=912285
++ # rtncode = self._process.poll()
++@@ -511,8 +512,10 @@ class MochitestUtilsMixin(object):
++ paths.sort(path_sort)
++
++ # Bug 883865 - add this functionality into manifestDestiny
++- with open(os.path.join(testdir, 'tests.json'), 'w') as manifestFile:
+++ manifestFile = open(os.path.join(testdir, 'tests.json'), 'w')
+++ if 1:
++ manifestFile.write(json.dumps({'tests': paths}))
+++ manifestFile.close()
++ options.manifestFile = 'tests.json'
++
++ return self.buildTestURL(options)
++@@ -529,9 +532,11 @@ class MochitestUtilsMixin(object):
++ self.server.start()
++
++ if options.pidFile != "":
++- with open(options.pidFile + ".xpcshell.pid", 'w') as f:
+++ f = open(options.pidFile + ".xpcshell.pid", 'w')
+++ if 1:
++ f.write("%s" % self.server._process.pid)
++
+++ f.close()
++ def startServers(self, options, debuggerInfo):
++ # start servers and set ports
++ # TODO: pass these values, don't set on `self`
++@@ -602,9 +607,11 @@ class MochitestUtilsMixin(object):
++ copy mochijar directory to profile as an extension so we have chrome://mochikit for all harness code
++ """
++ # Write chrome.manifest.
++- with open(os.path.join(options.profilePath, "extensions", "staged", "mochikit at mozilla.org", "chrome.manifest"), "a") as mfile:
+++ mfile = open(os.path.join(options.profilePath, "extensions", "staged", "mochikit at mozilla.org", "chrome.manifest"), "a")
+++ if 1:
++ mfile.write(chrome)
++
+++ mfile.close()
++ def addChromeToProfile(self, options):
++ "Adds MochiKit chrome tests to the profile."
++
++@@ -623,11 +630,14 @@ toolbar#nav-bar {
++ background-image: none !important;
++ }
++ """
++- with open(os.path.join(options.profilePath, "userChrome.css"), "a") as chromeFile:
+++ chromeFile = open(os.path.join(options.profilePath, "userChrome.css"), "a")
+++ if 1:
++ chromeFile.write(chrome)
++
+++ chromeFile.close()
++ manifest = os.path.join(options.profilePath, "tests.manifest")
++- with open(manifest, "w") as manifestFile:
+++ manifestFile = open(manifest, "w")
+++ if 1:
++ # Register chrome directory.
++ chrometestDir = os.path.join(os.path.abspath("."), SCRIPT_DIR) + "/"
++ if mozinfo.isWin:
++@@ -638,6 +648,7 @@ toolbar#nav-bar {
++ manifestFile.write("resource testing-common file:///%s\n" %
++ options.testingModulesDir)
++
+++ manifestFile.close()
++ # Call installChromeJar().
++ if not os.path.isdir(os.path.join(SCRIPT_DIR, self.jarDir)):
++ log.testFail("invalid setup: missing mochikit extension")
++@@ -660,7 +671,11 @@ overlay chrome://webapprt/content/webapp
++ def getExtensionsToInstall(self, options):
++ "Return a list of extensions to install in the profile"
++ extensions = options.extensionsToInstall or []
++- appDir = options.app[:options.app.rfind(os.sep)] if options.app else options.utilityPath
+++ appDir = None
+++ if options.app:
+++ appDir = options.app[:options.app.rfind(os.sep)]
+++ else:
+++ appDir = options.utilityPath
++
++ extensionDirs = [
++ # Extensions distributed with the test harness.
++@@ -720,7 +735,8 @@ class SSLTunnel:
++ def buildConfig(self, locations):
++ """Create the ssltunnel configuration file"""
++ configFd, self.configFile = tempfile.mkstemp(prefix="ssltunnel", suffix=".cfg")
++- with os.fdopen(configFd, "w") as config:
+++ config = os.fdopen(configFd, "w").__enter__()
+++ if 1:
++ config.write("httpproxy:1\n")
++ config.write("certdbdir:%s\n" % self.certPath)
++ config.write("forward:127.0.0.1:%s\n" % self.httpPort)
++@@ -731,6 +747,7 @@ class SSLTunnel:
++ if loc.scheme == "https" and "nocert" not in loc.options:
++ self.writeLocation(config, loc)
++
+++ config.__exit__(0, 0, 0)
++ def start(self):
++ """ Starts the SSL Tunnel """
++
++@@ -770,10 +787,13 @@ class Mochitest(MochitestUtilsMixin):
++ # environment function for browserEnv
++ self.environment = environment
++
++- # Max time in seconds to wait for server startup before tests will fail -- if
++- # this seems big, it's mostly for debug machines where cold startup
+++ # Max time in seconds to wait for server startup before tests will fail -- if # this seems big, it's mostly for debug machines where cold startup
++ # (particularly after a build) takes forever.
++- self.SERVER_STARTUP_TIMEOUT = 180 if mozinfo.info.get('debug') else 90
+++ self.SERVER_STARTUP_TIMEOUT = None
+++ if mozinfo.info.get('debug'):
+++ self.SERVER_STARTUP_TIMEOUT = 180
+++ else:
+++ self.SERVER_STARTUP_TIMEOUT = 90
++
++ # metro browser sub process id
++ self.browserProcessId = None
++@@ -795,9 +815,11 @@ class Mochitest(MochitestUtilsMixin):
++ # https://bugzilla.mozilla.org/show_bug.cgi?id=746243#c35
++
++ pwfilePath = os.path.join(options.profilePath, ".crtdbpw")
++- with open(pwfilePath, "w") as pwfile:
+++ pwfile = open(pwfilePath, "w")
+++ if 1:
++ pwfile.write("\n")
++
+++ pwfile.close()
++ # Pre-create the certification database for the profile
++ env = self.environment(xrePath=options.xrePath)
++ bin_suffix = mozinfo.info.get('bin_suffix', '')
++@@ -838,8 +860,8 @@ class Mochitest(MochitestUtilsMixin):
++ """ create the profile and add optional chrome bits and files if requested """
++ if options.browserChrome and options.timeout:
++ options.extraPrefs.append("testing.browserTestHarness.timeout=%d" % options.timeout)
++- options.extraPrefs.append("browser.tabs.remote=%s" % ('true' if options.e10s else 'false'))
++- options.extraPrefs.append("browser.tabs.remote.autostart=%s" % ('true' if options.e10s else 'false'))
+++ options.extraPrefs.append("browser.tabs.remote=%s" % (('false', 'true')[options.e10s]))
+++ options.extraPrefs.append("browser.tabs.remote.autostart=%s" % (('false', 'true)[options.e10s]))
++
++ # get extensions to install
++ extensions = self.getExtensionsToInstall(options)
++@@ -847,8 +869,10 @@ class Mochitest(MochitestUtilsMixin):
++ # web apps
++ appsPath = os.path.join(SCRIPT_DIR, 'profile_data', 'webapps_mochitest.json')
++ if os.path.exists(appsPath):
++- with open(appsPath) as apps_file:
+++ apps_file = open(appsPath)
+++ if 1:
++ apps = json.load(apps_file)
+++ apps_file.close()
++ else:
++ apps = None
++
++@@ -997,13 +1021,15 @@ class Mochitest(MochitestUtilsMixin):
++ log.info('INFO | zombiecheck | Reading PID log: %s', processLog)
++ processList = []
++ pidRE = re.compile(r'launched child process (\d+)$')
++- with open(processLog) as processLogFD:
+++ processLogFD = open(processLog)
+++ if 1:
++ for line in processLogFD:
++ log.info(line.rstrip())
++ m = pidRE.search(line)
++ if m:
++ processList.append(int(m.group(1)))
++
+++ processLogFD.close()
++ # kill zombies
++ foundZombie = False
++ for processPID in processList:
++@@ -1305,11 +1331,13 @@ class Mochitest(MochitestUtilsMixin):
++ processLeakLog(self.leak_report_file, options.leakThreshold)
++
++ if self.nsprLogs:
++- with zipfile.ZipFile("%s/nsprlog.zip" % browserEnv["MOZ_UPLOAD_DIR"], "w", zipfile.ZIP_DEFLATED) as logzip:
+++ logzip = zipfile.ZipFile("%s/nsprlog.zip" % browserEnv["MOZ_UPLOAD_DIR"], "w", zipfile.ZIP_DEFLATED).__enter__()
+++ if 1:
++ for logfile in glob.glob("%s/nspr*.log*" % tempfile.gettempdir()):
++ logzip.write(logfile)
++ os.remove(logfile)
++
+++ logzip.__exit__(0, 0, 0)
++ log.info("runtests.py | Running tests: end.")
++
++ if manifest is not None:
++@@ -1505,9 +1533,11 @@ class Mochitest(MochitestUtilsMixin):
++ d['testRoot'] = testRoot
++ content = json.dumps(d)
++
++- with open(os.path.join(options.profilePath, "testConfig.js"), "w") as config:
+++ config = open(os.path.join(options.profilePath, "testConfig.js"), "w")
+++ if 1:
++ config.write(content)
++
+++ config.close()
++ def installExtensionFromPath(self, options, path, extensionID = None):
++ """install an extension to options.profilePath"""
++
++diff -up comm-esr31/mozilla/testing/mochitest/runtestsremote.py.python3 comm-esr31/mozilla/testing/mochitest/runtestsremote.py
++--- comm-esr31/mozilla/testing/mochitest/runtestsremote.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mochitest/runtestsremote.py 2014-10-24 11:41:35.515879990 -0600
++@@ -407,9 +407,11 @@ class MochiRemote(Mochitest):
++
++ # In the future we could use LogParser: http://hg.mozilla.org/automation/logparser/
++ def addLogData(self):
++- with open(self.localLog) as currentLog:
+++ currentLog = open(self.localLog)
+++ if 1:
++ data = currentLog.readlines()
++
+++ currentLog.close()
++ restart = re.compile('0 INFO SimpleTest START.*')
++ reend = re.compile('([0-9]+) INFO TEST-START . Shutdown.*')
++ refail = re.compile('([0-9]+) INFO TEST-UNEXPECTED-FAIL.*')
++@@ -466,9 +468,11 @@ class MochiRemote(Mochitest):
++
++ # TODO: Consider not printing to stdout because we might be duplicating output
++ print '\n'.join(logFile)
++- with open(self.localLog, 'w') as localLog:
+++ localLog = open(self.localLog, 'w')
+++ if 1:
++ localLog.write('\n'.join(logFile))
++
+++ localLog.close()
++ if failed > 0:
++ return 1
++ return 0
++diff -up comm-esr31/mozilla/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py.python3 comm-esr31/mozilla/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py
++--- comm-esr31/mozilla/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py 2014-10-24 11:41:35.515879990 -0600
++@@ -14,7 +14,7 @@ __all__ = ['read_ini', # .ini reader
++
++ import fnmatch
++ import os
++-import re
+++import re, sre
++ import shutil
++ import sys
++
++@@ -258,12 +258,13 @@ class ExpressionParser(object):
++ passed to the constructor. Raises a ParseError if the expression
++ could not be parsed.
++ """
++- try:
+++ #try:
+++ if 1:
++ self.iter = self._tokenize()
++ self.token = self.iter.next()
++ return self.expression()
++- except:
++- raise ParseError("could not parse: %s; variables: %s" % (self.text, self.valuemapping))
+++ #except:
+++ # raise ParseError("could not parse: %s; variables: %s" % (self.text, self.valuemapping))
++
++ __call__ = parse
++
++@@ -318,7 +319,7 @@ def read_ini(fp, variables=None, default
++ fp = file(fp)
++
++ # read the lines
++- for (linenum, line) in enumerate(fp.readlines(), start=1):
+++ for (linenum, line) in enumerate(fp.readlines()):
++
++ stripped = line.strip()
++
++@@ -385,7 +386,7 @@ def read_ini(fp, variables=None, default
++ else:
++ filename = 'unknown'
++ raise Exception("Error parsing manifest file '%s', line %s" %
++- (filename, linenum))
+++ (filename, linenum+1))
++
++ # interpret the variables
++ def interpret_variables(global_dict, local_dict):
++@@ -961,12 +962,14 @@ class ManifestParser(object):
++
++ manifest_path = os.path.join(dirpath, filename)
++ if (dirnames or filenames) and not (os.path.exists(manifest_path) and overwrite):
++- with file(manifest_path, 'w') as manifest:
+++ manifest = file(manifest_path, 'w').__enter__()
+++ if 1:
++ for dirname in dirnames:
++ print >> manifest, '[include:%s]' % os.path.join(dirname, filename)
++ for _filename in filenames:
++ print >> manifest, '[%s]' % _filename
++
+++ manifest.__exit__(0, 0, 0)
++ # add to list of manifests
++ manifest_dict.setdefault(directory, manifest_path)
++
++diff -up comm-esr31/mozilla/testing/mozbase/manifestdestiny/tests/test_convert_directory.py.python3 comm-esr31/mozilla/testing/mozbase/manifestdestiny/tests/test_convert_directory.py
++--- comm-esr31/mozilla/testing/mozbase/manifestdestiny/tests/test_convert_directory.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/manifestdestiny/tests/test_convert_directory.py 2014-10-24 11:41:35.515879990 -0600
++@@ -136,9 +136,11 @@ subsuite =
++ newtempdir = tempfile.mkdtemp()
++ manifest_file = os.path.join(newtempdir, 'manifest.ini')
++ manifest_contents = str(convert([tempdir], relative_to=tempdir))
++- with file(manifest_file, 'w') as f:
+++ f = file(manifest_file, 'w').__enter__()
+++ if 1:
++ f.write(manifest_contents)
++
+++ f.__exit__(0, 0, 0)
++ # get the manifest
++ manifest = ManifestParser(manifests=(manifest_file,))
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py 2014-10-24 11:41:35.516879985 -0600
++@@ -579,7 +579,8 @@ class DeviceManagerADB(DeviceManager):
++
++ timeout = int(timeout)
++ retries = 0
++- with tempfile.SpooledTemporaryFile() as procOut:
+++ procOut = tempfile.SpooledTemporaryFile().__enter__()
+++ if 1:
++ while retries < retryLimit:
++ proc = subprocess.Popen(finalArgs, stdout=procOut, stderr=subprocess.STDOUT)
++ start_time = time.time()
++@@ -592,6 +593,7 @@ class DeviceManagerADB(DeviceManager):
++ retries += 1
++ continue
++ return ret_code
+++ procOut.__exit__(0, 0, 0)
++ raise DMError("Timeout exceeded for _checkCmd call after %d retries." % retries)
++
++ def chmodDir(self, remoteDir, mask="777"):
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanager.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanager.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanager.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanager.py 2014-10-24 11:41:35.516879985 -0600
++@@ -72,7 +72,11 @@ class DeviceManager(object):
++ @debug.setter
++ def debug_setter(self, newDebug):
++ self._logger.warn("dm.debug is deprecated. Use logLevel.")
++- newDebug = 5 if newDebug > 5 else newDebug # truncate >=5 to 5
+++ newDebug = None
+++ if newDebug > 5:
+++ newDebug = 5
+++ else:
+++ newDebug = newDebug # truncate >=5 to 5
++ levels = {5: mozlog.DEBUG, 3: mozlog.INFO, 2: mozlog.WARNING,
++ 1: mozlog.ERROR, 0: mozlog.CRITICAL}
++ self.logLevel = levels[newDebug]
++@@ -154,7 +158,8 @@ class DeviceManager(object):
++ if not self.fileExists(screencap):
++ raise DMError("Unable to capture screenshot on device: no screencap utility")
++
++- with open(filename, 'w') as pngfile:
+++ pngfile = open(filename, 'w')
+++ if 1:
++ # newer versions of screencap can write directly to a png, but some
++ # older versions can't
++ tempScreenshotFile = self.getDeviceRoot() + "/ss-dm.tmp"
++@@ -164,10 +169,13 @@ class DeviceManager(object):
++ buf = self.pullFile(tempScreenshotFile)
++ width = int(struct.unpack("I", buf[0:4])[0])
++ height = int(struct.unpack("I", buf[4:8])[0])
++- with open(filename, 'w') as pngfile:
+++ pngfile = open(filename, 'w')
+++ if 1:
++ pngfile.write(self._writePNG(buf[12:], width, height))
+++ pngfile.close()
++ self.removeFile(tempScreenshotFile)
++
+++ pngfile.close()
++ @abstractmethod
++ def pushFile(self, localFilename, remoteFilename, retryLimit=1, createDir=True):
++ """
++@@ -511,11 +519,11 @@ class DeviceManager(object):
++ """
++ # Based on: http://code.activestate.com/recipes/577443-write-a-png-image-in-native-python/
++ width_byte_4 = width * 4
++- raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in range(0, (height - 1) * width * 4, width_byte_4))
+++ raw_data = "".join(b'\x00' + buf[span:span + width_byte_4] for span in range(0, (height - 1) * width * 4, width_byte_4))
++ def png_pack(png_tag, data):
++ chunk_head = png_tag + data
++ return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
++- return b"".join([
+++ return "".join([
++ b'\x89PNG\r\n\x1a\n',
++ png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
++ png_pack(b'IDAT', zlib.compress(raw_data, 9)),
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py 2014-10-24 11:41:35.516879985 -0600
++@@ -119,8 +119,7 @@ class DeviceManagerSUT(DeviceManager):
++ """
++ # this allows us to move the retry logic outside of the _doCmds() to make it
++ # easier for debugging in the future.
++- # note that since cmdlist is a list of commands, they will all be retried if
++- # one fails. this is necessary in particular for pushFile(), where we don't want
+++ # note that since cmdlist is a list of commands, they will all be retried if # one fails. this is necessary in particular for pushFile(), where we don't want
++ # to accidentally send extra data if a failure occurs during data transmission.
++
++ retryLimit = retryLimit or self.retryLimit
++@@ -347,9 +346,11 @@ class DeviceManagerSUT(DeviceManager):
++
++ try:
++ filesize = os.path.getsize(localname)
++- with open(localname, 'rb') as f:
+++ f = open(localname, 'rb')
+++ if 1:
++ remoteHash = self._runCmds([{ 'cmd': 'push ' + destname + ' ' + str(filesize),
++ 'data': f.read() }], retryLimit=retryLimit).strip()
+++ f.close()
++ except OSError:
++ raise DMError("DeviceManager: Error reading file to push")
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/droid.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/droid.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/droid.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/droid.py 2014-10-24 11:41:35.516879985 -0600
++@@ -42,7 +42,7 @@ class DroidMixin(object):
++ "at once")
++
++ acmd = [ "am", "start" ] + self._getExtraAmStartArgs() + \
++- ["-W" if wait else '', "-n", "%s/%s" % (appName, activityName)]
+++ [('', "-W")[wait], "-n", "%s/%s" % (appName, activityName)]
++
++ if intent:
++ acmd.extend(["-a", intent])
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/sutini.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/sutini.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/sutini.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/sutini.py 2014-10-24 11:41:35.517879981 -0600
++@@ -70,7 +70,7 @@ def set_opt(cfg, s, o, dflt):
++
++ def bool_query(prompt, dflt):
++ while True:
++- i = raw_input('%s [%s] ' % (prompt, 'y' if dflt else 'n')).lower()
+++ i = raw_input('%s [%s] ' % (prompt, ('n', 'y')[dflt])).lower()
++ if not i or i[0] in ('y', 'n'):
++ break
++ print 'Enter y or n.'
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/Zeroconf.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/Zeroconf.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/Zeroconf.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/mozdevice/Zeroconf.py 2014-10-24 11:41:35.517879981 -0600
++@@ -1470,8 +1470,7 @@ class Zeroconf(object):
++ self.updateRecord(now, record)
++
++ def handleQuery(self, msg, addr, port):
++- """Deal with incoming query packets. Provides a response if
++- possible."""
+++ """Deal with incoming query packets. Provides a response if possible."""
++ out = None
++
++ # Support unicast client responses
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/genfiles.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/genfiles.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/genfiles.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/genfiles.py 2014-10-24 11:41:35.517879981 -0600
++@@ -10,19 +10,23 @@ import shutil
++
++
++ def gen_binary_file(path, size):
++- with open(path, 'wb') as f:
+++ f = open(path, 'wb')
+++ if 1:
++ for i in xrange(size):
++ byte = '%c' % randint(0, 255)
++ f.write(byte)
++
++
+++ f.close()
++ def gen_zip(path, files, stripped_prefix=''):
++- with ZipFile(path, 'w') as z:
+++ z = ZipFile(path, 'w').__enter__()
+++ if 1:
++ for f in files:
++ new_name = f.replace(stripped_prefix, '')
++ z.write(f, new_name)
++
++
+++ z.__exit__(0, 0, 0)
++ def mkdir(path, *args):
++ try:
++ os.mkdir(path, *args)
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/test_fileExists.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/test_fileExists.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/test_fileExists.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/sut_tests/test_fileExists.py 2014-10-24 11:41:35.517879981 -0600
++@@ -20,8 +20,10 @@ class FileExistsTestCase(DeviceManagerTe
++ def testOnRegularFile(self):
++ remote_path = posixpath.join(self.dm.getDeviceRoot(), 'testFile')
++ self.assertFalse(self.dm.fileExists(remote_path))
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ self.dm.pushFile(f.name, remote_path)
+++ f.__exit__(0, 0, 0)
++ self.assertTrue(self.dm.fileExists(remote_path))
++ self.dm.removeFile(remote_path)
++
++@@ -29,8 +31,10 @@ class FileExistsTestCase(DeviceManagerTe
++ remote_path = posixpath.join(self.dm.getDeviceRoot(), 'testDir')
++ remote_path_file = posixpath.join(remote_path, 'testFile')
++ self.assertFalse(self.dm.fileExists(remote_path))
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ self.dm.pushFile(f.name, remote_path_file)
+++ f.__exit__(0, 0, 0)
++ self.assertTrue(self.dm.fileExists(remote_path))
++ self.dm.removeFile(remote_path_file)
++ self.dm.removeDir(remote_path)
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_fileMethods.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_fileMethods.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_fileMethods.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_fileMethods.py 2014-10-24 11:41:35.518879977 -0600
++@@ -21,7 +21,8 @@ class TestFileMethods(unittest.TestCase)
++
++ def test_validateFile(self):
++
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ f.write(self.content)
++ f.flush()
++
++@@ -39,18 +40,21 @@ class TestFileMethods(unittest.TestCase)
++ d = mozdevice.DroidSUT("127.0.0.1", port=m.port, logLevel=mozlog.DEBUG)
++ self.assertFalse(d.validateFile('/sdcard/test/file', f.name))
++
+++ f.__exit__(0, 0, 0)
++ def test_getFile(self):
++
++ fname = "/mnt/sdcard/file"
++ commands = [("pull %s" % fname, "%s,%s\n%s" % (fname, len(self.content), self.content)),
++ ("hash %s" % fname, self.temp_hash)]
++
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ m = MockAgent(self, commands=commands)
++ d = mozdevice.DroidSUT("127.0.0.1", port=m.port, logLevel=mozlog.DEBUG)
++ # No error means success
++ self.assertEqual(None, d.getFile(fname, f.name))
++
+++ f.__exit__(0, 0, 0)
++ def test_getDirectory(self):
++
++ fname = "/mnt/sdcard/file"
++diff -up comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_push.py.python3 comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_push.py
++--- comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_push.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozdevice/tests/sut_push.py 2014-10-24 11:41:35.518879977 -0600
++@@ -20,7 +20,8 @@ class PushTest(unittest.TestCase):
++ a = MockAgent(self, commands = [("isdir /mnt/sdcard", "TRUE"),
++ (cmd, response[0])])
++ exceptionThrown = False
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ try:
++ f.write(pushfile)
++ f.flush()
++@@ -29,6 +30,7 @@ class PushTest(unittest.TestCase):
++ except mozdevice.DMError, e:
++ exceptionThrown = True
++ self.assertEqual(exceptionThrown, response[1])
+++ f.__exit__(0, 0, 0)
++ a.wait()
++
++ def test_push_dir(self):
++diff -up comm-esr31/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py.python3 comm-esr31/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py
++--- comm-esr31/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py 2014-10-24 11:41:35.518879977 -0600
++@@ -4,7 +4,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from contextlib import contextmanager
+++
++ import errno
++ import os
++ import shutil
++@@ -287,12 +287,12 @@ def tree(directory,
++ # if the top-level entry directory, print as passed
++ retval.append('%s%s%s'% (''.join(indent[:-1]),
++ dirpath_mark,
++- basename if retval else directory))
+++ (directory, basename)[retval]))
++ # add the files
++ if filenames:
++ last_file = filenames[-1]
++ retval.extend([('%s%s%s' % (''.join(indent),
++- files_end if filename == last_file else item_marker,
+++ (item_marker, files_end)[filename == last_file],
++ filename))
++ for index, filename in enumerate(filenames)])
++
++@@ -312,11 +312,13 @@ class NamedTemporaryFile(object):
++
++ Example usage:
++
++- with NamedTemporaryFile() as fh:
+++ fh = NamedTemporaryFile().__enter__()
+++ if 1:
++ fh.write(b'foobar')
++
++ print('Filename: %s' % fh.name)
++
+++ fh.__exit__(0, 0, 0)
++ see https://bugzilla.mozilla.org/show_bug.cgi?id=821362
++ """
++ def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='tmp',
++@@ -354,21 +356,23 @@ class NamedTemporaryFile(object):
++ os.unlink(self.__dict__['_path'])
++
++
++- at contextmanager
+++#@contextmanager
++ def TemporaryDirectory():
++ """
++ create a temporary directory using tempfile.mkdtemp, and then clean it up.
++
++ Example usage:
++- with TemporaryDirectory() as tmp:
+++ tmp = TemporaryDirectory().__enter__()
+++ if 1:
++ open(os.path.join(tmp, "a_temp_file"), "w").write("data")
++
+++ tmp.__exit__(0, 0, 0)
++ """
++ tempdir = tempfile.mkdtemp()
++- try:
++- yield tempdir
++- finally:
++- shutil.rmtree(tempdir)
+++ #try:
+++ yield tempdir
+++ #finally:
+++ shutil.rmtree(tempdir)
++
++
++ ### utilities dealing with URLs
++diff -up comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_remove.py.python3 comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_remove.py
++--- comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_remove.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_remove.py 2014-10-24 11:41:35.518879977 -0600
++@@ -32,8 +32,10 @@ class FileOpenCloseThread(threading.Thre
++ self.delete = delete
++
++ def run(self):
++- with open(self.path) as f:
+++ f = open(self.path)
+++ if 1:
++ time.sleep(self.delay)
+++ f.__exit__(0, 0, 0)
++ if self.delete:
++ try:
++ os.remove(self.path)
++@@ -79,9 +81,11 @@ class MozfileRemoveTestCase(unittest.Tes
++ """Test removing a closed file"""
++ # Open a file in the generated stub
++ filepath = os.path.join(self.tempdir, *stubs.files[1])
++- with open(filepath, 'w') as f:
+++ f = open(filepath, 'w').__enter__()
+++ if 1:
++ f.write('foo-bar')
++
+++ f.close()
++ # Folder should be deleted on all platforms
++ mozfile.remove(self.tempdir)
++ self.assertFalse(os.path.exists(self.tempdir))
++diff -up comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempdir.py.python3 comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempdir.py
++--- comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempdir.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempdir.py 2014-10-24 11:41:35.518879977 -0600
++@@ -18,23 +18,29 @@ class TestTemporaryDirectory(unittest.Te
++ def test_removed(self):
++ """ensure that a TemporaryDirectory gets removed"""
++ path = None
++- with TemporaryDirectory() as tmp:
+++ tmp = TemporaryDirectory().__enter__()
+++ if 1:
++ path = tmp
++ self.assertTrue(os.path.isdir(tmp))
++ tmpfile = os.path.join(tmp, "a_temp_file")
++ open(tmpfile, "w").write("data")
++ self.assertTrue(os.path.isfile(tmpfile))
+++ tmp.__exit__(0, 0, 0)
++ self.assertFalse(os.path.isdir(path))
++ self.assertFalse(os.path.exists(path))
++
++ def test_exception(self):
++ """ensure that TemporaryDirectory handles exceptions"""
++ path = None
++- with self.assertRaises(Exception):
++- with TemporaryDirectory() as tmp:
+++ self.assertRaises(Exception).__enter__()
+++ if 1:
+++ tmp = TemporaryDirectory().__enter__()
+++ if 1:
++ path = tmp
++ self.assertTrue(os.path.isdir(tmp))
++ raise Exception("oops")
+++ tmp.__exit__(0, 0, 0)
+++ self.assertRaises(Exception).__exit__(0, 0, 0)
++ self.assertFalse(os.path.isdir(path))
++ self.assertFalse(os.path.exists(path))
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempfile.py.python3 comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempfile.py
++--- comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempfile.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozfile/tests/test_tempfile.py 2014-10-24 11:41:35.519879973 -0600
++@@ -24,7 +24,8 @@ class TestNamedTemporaryFile(unittest.Te
++ """
++
++ test_string = "A simple test"
++- with mozfile.NamedTemporaryFile() as temp:
+++ temp = mozfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ # Test we can write to file
++ temp.write(test_string)
++ # Forced flush, so that we can read later
++@@ -33,6 +34,7 @@ class TestNamedTemporaryFile(unittest.Te
++ # Test we can open the file again on all platforms
++ self.assertEqual(open(temp.name).read(), test_string)
++
+++ temp.__exit__(0, 0, 0)
++ def test_iteration(self):
++ """ensure the line iterator works"""
++
++@@ -64,8 +66,10 @@ class TestNamedTemporaryFile(unittest.Te
++
++ # make a deleteable file; ensure it gets cleaned up
++ path = None
++- with mozfile.NamedTemporaryFile(delete=True) as tf:
+++ tf = mozfile.NamedTemporaryFile(delete=True).__enter__()
+++ if 1:
++ path = tf.name
+++ tf.__exit__(0, 0, 0)
++ self.assertTrue(isinstance(path, basestring))
++ self.assertFalse(os.path.exists(path))
++
++@@ -80,8 +84,10 @@ class TestNamedTemporaryFile(unittest.Te
++ # Now the same thing but we won't delete the file
++ path = None
++ try:
++- with mozfile.NamedTemporaryFile(delete=False) as tf:
+++ tf = mozfile.NamedTemporaryFile(delete=False).__enter__()
+++ if 1:
++ path = tf.name
+++ tf.__exit__(0, 0, 0)
++ self.assertTrue(os.path.exists(path))
++ finally:
++ if path and os.path.exists(path):
++diff -up comm-esr31/mozilla/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py.python3 comm-esr31/mozilla/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py
++--- comm-esr31/mozilla/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py 2014-10-24 11:41:35.519879973 -0600
++@@ -213,8 +213,7 @@ class MozHttpd(object):
++ from <self.docroot>/<host>/.
++
++ For example, the request "GET http://foo.bar/dir/file.html" would
++- (assuming no handlers match) serve <docroot>/dir/file.html if
++- proxy_host_dirs is False, or <docroot>/foo.bar/dir/file.html if it is
+++ (assuming no handlers match) serve <docroot>/dir/file.html if proxy_host_dirs is False, or <docroot>/foo.bar/dir/file.html if it is
++ True.
++ """
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/basic.py.python3 comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/basic.py
++--- comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/basic.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/basic.py 2014-10-24 11:41:35.519879973 -0600
++@@ -27,9 +27,11 @@ class TestBasic(unittest.TestCase):
++ sizes[k].append(fpath)
++
++ # Write binary string to file
++- with open(fpath, 'wb') as f:
+++ f = open(fpath, 'wb')
+++ if 1:
++ f.write(sizes[k][1])
++
+++ f.close()
++ server = mozhttpd.MozHttpd(docroot=tempdir)
++ server.start()
++ server_url = server.get_url()
++diff -up comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/paths.py.python3 comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/paths.py
++--- comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/paths.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozhttpd/tests/paths.py 2014-10-24 11:41:35.519879973 -0600
++@@ -16,13 +16,16 @@ class PathTest(unittest.TestCase):
++ self.assertEqual(f.read(), expected_contents)
++
++ def try_get_expect_404(self, url):
++- with self.assertRaises(urllib2.HTTPError) as cm:
+++ cm = self.assertRaises(urllib2.HTTPError).__enter__()
+++ if 1:
++ urllib2.urlopen(url)
+++ cm.__exit__(0, 0, 0)
++ self.assertEqual(404, cm.exception.code)
++
++ def test_basic(self):
++ """Test that requests to docroot and a path mapping work as expected."""
++- with TemporaryDirectory() as d1, TemporaryDirectory() as d2:
+++ d1, TemporaryDirectory() = d2 = TemporaryDirectory().__enter__()
+++ if 1:
++ open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
++ open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents")
++ httpd = mozhttpd.MozHttpd(port=0,
++@@ -35,9 +38,11 @@ class PathTest(unittest.TestCase):
++ self.try_get_expect_404(httpd.get_url("/files/test2_nope.txt"))
++ httpd.stop()
++
+++ d2.__exit__(0, 0, 0)
++ def test_substring_mappings(self):
++ """Test that a path mapping that's a substring of another works."""
++- with TemporaryDirectory() as d1, TemporaryDirectory() as d2:
+++ d1, TemporaryDirectory() = d2 = TemporaryDirectory().__enter__()
+++ if 1:
++ open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
++ open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents")
++ httpd = mozhttpd.MozHttpd(port=0,
++@@ -49,9 +54,11 @@ class PathTest(unittest.TestCase):
++ self.try_get(httpd.get_url("/abc/test2.txt"), "test 2 contents")
++ httpd.stop()
++
+++ d2.__exit__(0, 0, 0)
++ def test_multipart_path_mapping(self):
++ """Test that a path mapping with multiple directories works."""
++- with TemporaryDirectory() as d1:
+++ d1 = TemporaryDirectory().__enter__()
+++ if 1:
++ open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
++ httpd = mozhttpd.MozHttpd(port=0,
++ path_mappings={'/abc/def/ghi': d1}
++@@ -62,14 +69,17 @@ class PathTest(unittest.TestCase):
++ self.try_get_expect_404(httpd.get_url("/abc/def/test1.txt"))
++ httpd.stop()
++
+++ d1.__exit__(0, 0, 0)
++ def test_no_docroot(self):
++ """Test that path mappings with no docroot work."""
++- with TemporaryDirectory() as d1:
+++ d1 = TemporaryDirectory().__enter__()
+++ if 1:
++ httpd = mozhttpd.MozHttpd(port=0,
++ path_mappings={'/foo': d1})
++ httpd.start(block=False)
++ self.try_get_expect_404(httpd.get_url())
++ httpd.stop()
++
+++ d1.__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ unittest.main()
++diff -up comm-esr31/mozilla/testing/mozbase/mozinfo/tests/test.py.python3 comm-esr31/mozilla/testing/mozbase/mozinfo/tests/test.py
++--- comm-esr31/mozilla/testing/mozbase/mozinfo/tests/test.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozinfo/tests/test.py 2014-10-24 11:41:35.519879973 -0600
++@@ -41,24 +41,30 @@ class TestMozinfo(unittest.TestCase):
++ def test_update_file(self):
++ """Test that mozinfo.update can load a JSON file."""
++ j = os.path.join(self.tempdir, "mozinfo.json")
++- with open(j, "w") as f:
+++ f = open(j, "w")
+++ if 1:
++ f.write(json.dumps({"foo": "xyz"}))
+++ f.__exit__(0, 0, 0)
++ mozinfo.update(j)
++ self.assertEqual(mozinfo.info["foo"], "xyz")
++
++ def test_update_file_invalid_json(self):
++ """Test that mozinfo.update handles invalid JSON correctly"""
++ j = os.path.join(self.tempdir,'test.json')
++- with open(j, 'w') as f:
+++ f = open(j, 'w')
+++ if 1:
++ f.write('invalid{"json":')
+++ f.__exit__(0, 0, 0)
++ self.assertRaises(ValueError,mozinfo.update,[j])
++
++ def test_find_and_update_file(self):
++ """Test that mozinfo.find_and_update_from_json can
++ find mozinfo.json in a directory passed to it."""
++ j = os.path.join(self.tempdir, "mozinfo.json")
++- with open(j, "w") as f:
+++ f = open(j, "w").__enter__()
+++ if 1:
++ f.write(json.dumps({"foo": "abcdefg"}))
+++ f.__exit__(0, 0, 0)
++ self.assertEqual(mozinfo.find_and_update_from_json(self.tempdir), j)
++ self.assertEqual(mozinfo.info["foo"], "abcdefg")
++
++@@ -66,8 +72,10 @@ class TestMozinfo(unittest.TestCase):
++ """Test that mozinfo.find_and_update_from_json can
++ handle invalid JSON"""
++ j = os.path.join(self.tempdir, "mozinfo.json")
++- with open(j, 'w') as f:
+++ f = open(j, 'w').__enter__()
+++ if 1:
++ f.write('invalid{"json":')
+++ f.close()
++ self.assertRaises(ValueError, mozinfo.find_and_update_from_json, self.tempdir)
++
++
++@@ -75,13 +83,17 @@ class TestMozinfo(unittest.TestCase):
++ """Test that mozinfo.find_and_update_from_json can
++ find mozinfo.json using the mozbuild module."""
++ j = os.path.join(self.tempdir, "mozinfo.json")
++- with open(j, "w") as f:
+++ f = open(j, "w").__enter__()
+++ if 1:
++ f.write(json.dumps({"foo": "123456"}))
+++ f.close()
++ m = mock.MagicMock()
++ # Mock the value of MozbuildObject.from_environment().topobjdir.
++ m.MozbuildObject.from_environment.return_value.topobjdir = self.tempdir
++- with mock.patch.dict(sys.modules, {"mozbuild": m, "mozbuild.base": m}):
+++ mock.patch.dict(sys.modules, {"mozbuild": m, "mozbuild.base": m}).__enter__()
+++ if 1:
++ self.assertEqual(mozinfo.find_and_update_from_json(), j)
+++ mock.patch.dict(sys.modules, {"mozbuild": m, "mozbuild.base": m}).__exit__(0, 0, 0)
++ self.assertEqual(mozinfo.info["foo"], "123456")
++
++ if __name__ == '__main__':
++diff -up comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/logger.py.python3 comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/logger.py
++--- comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/logger.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/logger.py 2014-10-24 11:41:35.520879968 -0600
++@@ -72,8 +72,7 @@ class MozLogger(_LoggerClass):
++
++ # If the logger is fed a level number unknown to the logging
++ # module, getLevelName will return a string. Unfortunately,
++- # the logging module will raise a type error elsewhere if
++- # the level is not an integer.
+++ # the logging module will raise a type error elsewhere if # the level is not an integer.
++ if not isinstance(level, int):
++ level = _default_level
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py.python3 comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py
++--- comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py 2014-10-24 11:41:35.520879968 -0600
++@@ -38,12 +38,14 @@ class HTMLFormatter(base.BaseFormatter):
++ def suite_start(self, data):
++ self.suite_times["start"] = data["time"]
++ self.suite_name = data["source"]
++- with open(os.path.join(base_path, "style.css")) as f:
+++ f = open(os.path.join(base_path, "style.css"))
+++ if 1:
++ self.head = html.head(
++ html.meta(charset="utf-8"),
++ html.title(data["source"]),
++ html.style(raw(f.read())))
++
+++ f.close()
++ def suite_end(self, data):
++ self.suite_times["end"] = data["time"]
++ return self.generate_html()
++@@ -123,7 +125,8 @@ class HTMLFormatter(base.BaseFormatter):
++
++ def generate_html(self):
++ generated = datetime.datetime.now()
++- with open(os.path.join(base_path, "main.js")) as main_f:
+++ main_f = open(os.path.join(base_path, "main.js"))
+++ if 1:
++ doc = html.html(
++ self.head,
++ html.body(
++@@ -157,6 +160,7 @@ class HTMLFormatter(base.BaseFormatter):
++ html.th('Links')]), id='results-table-head'),
++ html.tbody(self.result_rows, id='results-table-body')], id='results-table'))))
++
+++ main_f.close()
++ return doc.unicode(indent=2)
++
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py.python3 comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py
++--- comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py 2014-10-24 11:41:35.520879968 -0600
++@@ -53,7 +53,11 @@ class BaseMachFormatter(base.BaseFormatt
++ expected_str = ""
++
++ subtests = self._get_subtest_data(data)
++- unexpected = subtests["unexpected"] + (1 if "expected" in data else 0)
+++ unexpected = None
+++ if "expected" in data:
+++ unexpected = subtests["unexpected"] + (1
+++ else:
+++ unexpected = 0)
++
++ return "Harness status %s%s. Subtests passed %i/%i. Unexpected %i" % (
++ data["status"], expected_str, subtests["pass"],
++diff -up comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py.python3 comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py
++--- comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py 2014-10-24 11:41:35.520879968 -0600
++@@ -60,10 +60,13 @@ class StreamHandler(BaseHandler):
++ formatted = self.formatter(data)
++ if not formatted:
++ return
++- with self._lock:
+++ self._lock.__enter__()
+++ if 1:
++ #XXX Should encoding be the formatter's responsibility?
++ try:
++ self.stream.write(formatted.encode("utf8"))
++ except:
++ raise
++ self.stream.flush()
+++ self._lock.__exit__(0, 0, 0)
+++
++diff -up comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/structuredlog.py.python3 comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/structuredlog.py
++--- comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/structuredlog.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozlog/mozlog/structured/structuredlog.py 2014-10-24 11:41:35.520879968 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import sys
++ from collections import defaultdict
++@@ -90,11 +90,13 @@ class StructuredLogger(object):
++ def _log_data(self, action, data=None):
++ if data is None:
++ data = {}
++- with self._lock:
+++ self._lock.__enter__()
+++ if 1:
++ log_data = self._make_log_data(action, data)
++ for handler in self.handlers:
++ handler(log_data)
++
+++ self._lock.__exit__(0, 0, 0)
++ def _make_log_data(self, action, data):
++ all_data = {"action": action,
++ "time": int(time.time() * 1000),
++diff -up comm-esr31/mozilla/testing/mozbase/moznetwork/moznetwork/moznetwork.py.python3 comm-esr31/mozilla/testing/mozbase/moznetwork/moznetwork/moznetwork.py
++--- comm-esr31/mozilla/testing/mozbase/moznetwork/moznetwork/moznetwork.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/moznetwork/moznetwork/moznetwork.py 2014-10-24 11:41:35.521879964 -0600
++@@ -22,7 +22,11 @@ def _get_interface_list():
++ max_iface = 32 # Maximum number of interfaces(Aribtrary)
++ bytes = max_iface * 32
++ is_32bit = (8 * struct.calcsize("P")) == 32 # Set Architecture
++- struct_size = 32 if is_32bit else 40
+++ struct_size = None
+++ if is_32bit:
+++ struct_size = 32
+++ else:
+++ struct_size = 40
++
++ try:
++ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
++diff -up comm-esr31/mozilla/testing/mozbase/moznetwork/tests/test.py.python3 comm-esr31/mozilla/testing/mozbase/moznetwork/tests/test.py
++--- comm-esr31/mozilla/testing/mozbase/moznetwork/tests/test.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/moznetwork/tests/test.py 2014-10-24 11:41:35.521879964 -0600
++@@ -64,7 +64,8 @@ class TestGetIP(unittest.TestCase):
++
++ if mozinfo.isLinux or mozinfo.isMac:
++
++- with mock.patch('socket.gethostbyname') as byname:
+++ byname = mock.patch('socket.gethostbyname').__enter__()
+++ if 1:
++ # Force socket.gethostbyname to return None
++ byname.return_value = None
++
++@@ -74,5 +75,6 @@ class TestGetIP(unittest.TestCase):
++ self.assertTrue(verify_ip_in_list(ip))
++
++
+++ byname.__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ unittest.main()
++diff -up comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess_params.py.python3 comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess_params.py
++--- comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess_params.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess_params.py 2014-10-24 11:41:35.521879964 -0600
++@@ -17,7 +17,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['ls','-l'], processOutputLine=output)
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++@@ -28,7 +28,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['ls','-l'], processOutputLine=[output])
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++@@ -40,7 +40,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['sleep', '2'], onTimeout=timeout)
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++@@ -51,7 +51,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['sleep', '2'], onTimeout=[timeout])
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++@@ -62,7 +62,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['sleep', '1'], onFinish=finish)
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++@@ -73,7 +73,7 @@ class ParamTests(unittest.TestCase):
++ err = None
++ try:
++ p = processhandler.ProcessHandler(['sleep', '1'], onFinish=[finish])
++- except (TypeError, AttributeError) as e:
+++ except (TypeError, AttributeError), e:
++ err = e
++ self.assertFalse(err)
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess.py.python3 comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess.py
++--- comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprocess/tests/test_mozprocess.py 2014-10-24 11:41:35.521879964 -0600
++@@ -117,7 +117,7 @@ class ProcTest(unittest.TestCase):
++ if os.path.exists(path):
++ try:
++ os.remove(path)
++- except OSError as e:
+++ except OSError, e:
++ errors.append(str(e))
++ if errors:
++ raise OSError("Error(s) encountered tearing down %s.%s:\n%s" % (cls.__module__, cls.__name__, '\n'.join(errors)))
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/addons.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/addons.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/addons.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/addons.py 2014-10-24 11:41:35.522879960 -0600
++@@ -275,8 +275,10 @@ class AddonManager(object):
++ finally:
++ compressed_file.close()
++ elif os.path.isdir(addon_path):
++- with open(os.path.join(addon_path, 'install.rdf'), 'r') as f:
+++ f = open(os.path.join(addon_path, 'install.rdf'), 'r')
+++ if 1:
++ manifest = f.read()
+++ f.close()
++ else:
++ raise IOError('Add-on path is neither an XPI nor a directory: %s' % addon_path)
++ except (IOError, KeyError), e:
++@@ -334,8 +336,7 @@ class AddonManager(object):
++ if not os.path.isdir(path):
++ return
++
++- addons = [os.path.join(path, x) for x in os.listdir(path) if
++- self.is_addon(os.path.join(path, x))]
+++ addons = [os.path.join(path, x) for x in os.listdir(path) if self.is_addon(os.path.join(path, x))]
++ addons.sort()
++
++ # install each addon
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/profile.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/profile.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/profile.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/mozprofile/profile.py 2014-10-24 11:41:35.522879960 -0600
++@@ -206,8 +206,10 @@ class Profile(object):
++ """
++
++ path = os.path.join(self.profile, filename)
++- with file(path) as f:
+++ f = file(path).__enter__()
+++ if 1:
++ lines = f.read().splitlines()
+++ f.__exit__(0, 0, 0)
++ def last_index(_list, value):
++ """
++ returns the last index of an item;
++@@ -231,8 +233,10 @@ class Profile(object):
++
++ # write the prefs
++ cleaned_prefs = '\n'.join(lines[:s] + lines[e+1:])
++- with file(path, 'w') as f:
+++ f = file(path, 'w').__enter__()
+++ if 1:
++ f.write(cleaned_prefs)
+++ f.__exit__(0, 0, 0)
++ return True
++
++ ### methods for introspection
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/tests/addon_stubs.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/tests/addon_stubs.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/tests/addon_stubs.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/tests/addon_stubs.py 2014-10-24 11:41:35.522879960 -0600
++@@ -49,18 +49,22 @@ def generate_addon(addon_id, path=None,
++ # Write install.rdf for addon
++ if stubs[addon_id]:
++ install_rdf = os.path.join(addon_dir, 'install.rdf')
++- with open(install_rdf, 'w') as f:
+++ f = open(install_rdf, 'w')
+++ if 1:
++ manifest = os.path.join(here, 'install_manifests', stubs[addon_id])
++ f.write(open(manifest, 'r').read())
++
+++ f.close()
++ if not xpi:
++ return addon_dir
++
++ # Generate the .xpi for the addon
++ xpi_file = os.path.join(tmpdir, (name or addon_id) + '.xpi')
++- with zipfile.ZipFile(xpi_file, 'w') as x:
+++ x = zipfile.ZipFile(xpi_file, 'w').__enter__()
+++ if 1:
++ x.write(install_rdf, install_rdf[len(addon_dir):])
++
+++ x.__exit__(0, 0, 0)
++ # Ensure we remove the temporary folder to not install the addon twice
++ mozfile.rmtree(addon_dir)
++
++@@ -72,8 +76,10 @@ def generate_manifest(addon_list, path=N
++ addons = [generate_addon(addon, path=tmpdir) for addon in addon_list]
++
++ manifest = os.path.join(tmpdir, 'manifest.ini')
++- with open(manifest, 'w') as f:
+++ f = open(manifest, 'w')
+++ if 1:
++ for addon in addons:
++ f.write('[' + addon + ']\n')
++
+++ f.close()
++ return manifest
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/tests/permissions.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/tests/permissions.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/tests/permissions.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/tests/permissions.py 2014-10-24 11:41:35.522879960 -0600
++@@ -149,7 +149,11 @@ http://127.0.0.1:8888 privileg
++
++ self.assertEqual(len(entries), 3)
++
++- columns = 8 if version == 3 else 6
+++ columns = None
+++ if version == 3:
+++ columns = 8
+++ else:
+++ columns = 6
++ self.assertEqual(len(entries[0]), columns)
++ for x in range(4, columns):
++ self.assertEqual(entries[0][x], 0)
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_addons.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_addons.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_addons.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_addons.py 2014-10-24 11:41:35.522879960 -0600
++@@ -64,8 +64,7 @@ class TestAddonsManager(unittest.TestCas
++ self.assertEqual(self.am.installed_addons, [addon_xpi])
++ self.am.clean()
++
++- # Even if it is the same id the add-on should be installed twice, if
++- # specified via XPI and folder
+++ # Even if it is the same id the add-on should be installed twice, if # specified via XPI and folder
++ self.am.install_addons([addon_folder, addon_xpi])
++ self.assertEqual(len(self.am.installed_addons), 2)
++ self.assertIn(addon_folder, self.am.installed_addons)
++diff -up comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_preferences.py.python3 comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_preferences.py
++--- comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_preferences.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozprofile/tests/test_preferences.py 2014-10-24 11:41:35.523879956 -0600
++@@ -241,10 +241,12 @@ user_pref("webgl.force-enabled", true);
++ path = None
++ read_prefs = None
++ try:
++- with mozfile.NamedTemporaryFile(suffix='.js', delete=False) as f:
+++ f = mozfile.NamedTemporaryFile(suffix='.js', delete=False).__enter__()
+++ if 1:
++ path = f.name
++ preferences.write(f, _prefs)
++
+++ f.__exit__(0, 0, 0)
++ # read them back and ensure we get what we put in
++ read_prefs = dict(Preferences.read_prefs(path))
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/base.py.python3 comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/base.py
++--- comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/base.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/base.py 2014-10-24 11:41:35.523879956 -0600
++@@ -11,7 +11,7 @@ from mozprocess.processhandler import Pr
++ import mozcrash
++ import mozlog
++
++-from .errors import RunnerNotStartedError
+++from errors import RunnerNotStartedError
++
++
++ # we can replace these methods with 'abc'
++@@ -99,8 +99,7 @@ class Runner(object):
++
++ :param timeout: if not None, will return after timeout seconds.
++ Use is_running() to determine whether or not a
++- timeout occured. Timeout is ignored if
++- interactive was set to True.
+++ timeout occured. Timeout is ignored if interactive was set to True.
++
++ """
++ if self.is_running():
++diff -up comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/__init__.py.python3 comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/__init__.py
++--- comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/__init__.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/__init__.py 2014-10-24 11:41:35.523879956 -0600
++@@ -2,10 +2,10 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this file,
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from .errors import *
++-from .local import *
++-from .local import LocalRunner as Runner
++-from .remote import *
+++from errors import *
+++from local import *
+++from local import LocalRunner as Runner
+++from remote import *
++
++ runners = local_runners
++ runners.update(remote_runners)
++diff -up comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/local.py.python3 comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/local.py
++--- comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/local.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/local.py 2014-10-24 11:41:35.523879956 -0600
++@@ -17,8 +17,8 @@ if mozinfo.isMac:
++
++ from mozprofile import Profile, FirefoxProfile, MetroFirefoxProfile, ThunderbirdProfile, MozProfileCLI
++
++-from .base import Runner
++-from .utils import findInPath, get_metadata_from_egg
+++from base import Runner
+++from utils import findInPath, get_metadata_from_egg
++
++
++ __all__ = ['CLI',
++diff -up comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/remote.py.python3 comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/remote.py
++--- comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/remote.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozrunner/mozrunner/remote.py 2014-10-24 11:41:35.523879956 -0600
++@@ -17,7 +17,7 @@ from mozdevice import DMError
++ import mozfile
++ import mozlog
++
++-from .base import Runner
+++from base import Runner
++
++
++ __all__ = ['B2GRunner',
++diff -up comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py.python3 comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py
++--- comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py 2014-10-24 11:41:35.524879951 -0600
++@@ -12,12 +12,12 @@ try:
++ except Exception:
++ psutil = None
++
++-from collections import (
+++from mycollections import (
++ OrderedDict,
++ namedtuple,
++ )
++
++-from contextlib import contextmanager
+++
++
++
++ def _collect(pipe, poll_interval):
++@@ -126,9 +126,11 @@ class SystemResourceMonitor(object):
++ monitor.record_event('foo_did_stuff')
++
++ # Record that we're about to perform a possibly long-running event.
++- with monitor.phase('long_job'):
+++ monitor.phase('long_job').__enter__()
+++ if 1:
++ foo.do_long_running_job()
++
+++ monitor.phase('long_job').__exit__(0, 0, 0)
++ # Stop recording. Currently we need to stop before data is available.
++ monitor.stop()
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py.python3 comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py
++--- comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py 2014-10-24 11:41:35.524879951 -0600
++@@ -47,12 +47,14 @@ class TestResourceMonitor(unittest.TestC
++ monitor.start()
++ time.sleep(1)
++
++- with monitor.phase('phase1'):
+++ monitor.phase('phase1').__enter__()
+++ if 1:
++ time.sleep(1)
++
++ with monitor.phase('phase2'):
++ time.sleep(1)
++
+++ monitor.phase('phase1').__exit__(0, 0, 0)
++ monitor.stop()
++
++ self.assertEqual(len(monitor.phases), 2)
++diff -up comm-esr31/mozilla/testing/mozbase/moztest/moztest/output/base.py.python3 comm-esr31/mozilla/testing/mozbase/moztest/moztest/output/base.py
++--- comm-esr31/mozilla/testing/mozbase/moztest/moztest/output/base.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/moztest/moztest/output/base.py 2014-10-24 11:41:35.524879951 -0600
++@@ -3,7 +3,7 @@
++ # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++
++-from __future__ import with_statement
+++
++ from contextlib import closing
++ from StringIO import StringIO
++
++@@ -30,11 +30,13 @@ class Output(object):
++
++ def dump_string(self, results_collection):
++ """ Returns the string representation of the results collection """
++- with closing(StringIO()) as s:
+++ s = closing(StringIO()).__enter__()
+++ if 1:
++ self.serialize(results_collection, s)
++ return s.getvalue()
++
++
+++ s.__exit__(0, 0, 0)
++ # helper functions
++ def count(iterable):
++ """ Return the count of an iterable. Useful for generators. """
++diff -up comm-esr31/mozilla/testing/mozbase/moztest/moztest/results.py.python3 comm-esr31/mozilla/testing/mozbase/moztest/moztest/results.py
++--- comm-esr31/mozilla/testing/mozbase/moztest/moztest/results.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/moztest/moztest/results.py 2014-10-24 11:41:35.524879951 -0600
++@@ -90,7 +90,11 @@ class TestResult(object):
++ self.name = name
++ self.test_class = test_class
++ self.context = context
++- self.time_start = time_start if time_start is not None else time.time()
+++ self.time_start = None
+++ if time_start is not None:
+++ self.time_start = time_start
+++ else:
+++ self.time_start = time.time()
++ self.time_end = None
++ self._result_expected = result_expected
++ self._result_actual = None
++@@ -173,7 +177,11 @@ class TestResult(object):
++ if isinstance(output, basestring):
++ output = output.splitlines()
++
++- self.time_end = time_end if time_end is not None else time.time()
+++ self.time_end = None
+++ if time_end is not None:
+++ self.time_end = time_end
+++ else:
+++ self.time_end = time.time()
++ self.output = output or self.output
++ self.reason = reason
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozversion/mozversion/mozversion.py.python3 comm-esr31/mozilla/testing/mozbase/mozversion/mozversion/mozversion.py
++--- comm-esr31/mozilla/testing/mozbase/mozversion/mozversion/mozversion.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozversion/mozversion/mozversion.py 2014-10-24 11:41:35.524879951 -0600
++@@ -104,8 +104,10 @@ class B2GVersion(Version):
++ gaia_commit = os.path.join(tempdir, 'gaia_commit.txt')
++ try:
++ zip_file = zipfile.ZipFile(app_zip.name)
++- with open(gaia_commit, 'w') as f:
+++ f = open(gaia_commit, 'w')
+++ if 1:
++ f.write(zip_file.read('resources/gaia_commit.txt'))
+++ f.__exit__(0, 0, 0)
++ except zipfile.BadZipfile:
++ self.info('Unable to unzip application.zip, falling back to '
++ 'system unzip')
++@@ -113,11 +115,13 @@ class B2GVersion(Version):
++ call(['unzip', '-j', app_zip.name, 'resources/gaia_commit.txt',
++ '-d', tempdir])
++
++- with open(gaia_commit) as f:
+++ f = open(gaia_commit)
+++ if 1:
++ changeset, date = f.read().splitlines()
++ self._info['gaia_changeset'] = re.match(
++ '^\w{40}$', changeset) and changeset or None
++ self._info['gaia_date'] = date
+++ f.__exit__(0, 0, 0)
++ finally:
++ mozfile.remove(tempdir)
++
++@@ -141,8 +145,10 @@ class LocalB2GVersion(B2GVersion):
++ path, 'gaia', 'profile', 'webapps',
++ 'settings.gaiamobile.org', 'application.zip')
++ if os.path.exists(zip_path):
++- with open(zip_path, 'rb') as zip_file:
+++ zip_file = open(zip_path, 'rb').__enter__()
+++ if 1:
++ self.get_gaia_info(zip_file)
+++ zip_file.__exit__(0, 0, 0)
++ else:
++ self.warn('Error pulling gaia file')
++
++@@ -170,18 +176,22 @@ class RemoteB2GVersion(B2GVersion):
++
++ tempdir = tempfile.mkdtemp()
++ for ini in ('application', 'platform'):
++- with open(os.path.join(tempdir, '%s.ini' % ini), 'w') as f:
+++ f = open(os.path.join(tempdir, '%s.ini' % ini), 'w').__enter__()
+++ if 1:
++ f.write(dm.pullFile('/system/b2g/%s.ini' % ini))
++ f.flush()
+++ f.close()
++ self.get_gecko_info(tempdir)
++ mozfile.remove(tempdir)
++
++ for path in ['/system/b2g', '/data/local']:
++ path += '/webapps/settings.gaiamobile.org/application.zip'
++ if dm.fileExists(path):
++- with tempfile.NamedTemporaryFile() as f:
+++ f = tempfile.NamedTemporaryFile().__enter__()
+++ if 1:
++ dm.getFile(path, f.name)
++ self.get_gaia_info(f)
+++ f.close()
++ break
++ else:
++ self.warn('Error pulling gaia file')
++diff -up comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_b2g.py.python3 comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_b2g.py
++--- comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_b2g.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_b2g.py 2014-10-24 11:41:35.525879947 -0600
++@@ -20,12 +20,16 @@ class SourcesTest(unittest.TestCase):
++ self.tempdir = tempfile.mkdtemp()
++
++ self.binary = os.path.join(self.tempdir, 'binary')
++- with open(self.binary, 'w') as f:
+++ f = open(self.binary, 'w')
+++ if 1:
++ f.write('foobar')
++
++- with open(os.path.join(self.tempdir, 'application.ini'), 'w') as f:
+++ f.__exit__(0, 0, 0)
+++ f = open(os.path.join(self.tempdir, 'application.ini'), 'w').__enter__()
+++ if 1:
++ f.writelines("""[App]\nName = B2G\n""")
++
+++ f.close()
++ def tearDown(self):
++ mozfile.remove(self.tempdir)
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_binary.py.python3 comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_binary.py
++--- comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_binary.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_binary.py 2014-10-24 11:41:35.525879947 -0600
++@@ -34,28 +34,38 @@ SourceRepository = PlatformSourceRepo
++ self.tempdir = tempfile.mkdtemp()
++
++ self.binary = os.path.join(self.tempdir, 'binary')
++- with open(self.binary, 'w') as f:
+++ f = open(self.binary, 'w')
+++ if 1:
++ f.write('foobar')
++
+++ f.__exit__(0, 0, 0)
++ def tearDown(self):
++ os.chdir(self.cwd)
++ mozfile.remove(self.tempdir)
++
++ def test_binary(self):
++- with open(os.path.join(self.tempdir, 'application.ini'), 'w') as f:
+++ f = open(os.path.join(self.tempdir, 'application.ini'), 'w')
+++ if 1:
++ f.writelines(self.application_ini)
++
++- with open(os.path.join(self.tempdir, 'platform.ini'), 'w') as f:
+++ f.__exit__(0, 0, 0)
+++ f = open(os.path.join(self.tempdir, 'platform.ini'), 'w').__enter__()
+++ if 1:
++ f.writelines(self.platform_ini)
++
+++ f.__exit__(0, 0, 0)
++ self._check_version(get_version(self.binary))
++
++ def test_binary_in_current_path(self):
++- with open(os.path.join(self.tempdir, 'application.ini'), 'w') as f:
+++ f = open(os.path.join(self.tempdir, 'application.ini'), 'w').__enter__()
+++ if 1:
++ f.writelines(self.application_ini)
++
++- with open(os.path.join(self.tempdir, 'platform.ini'), 'w') as f:
+++ f.close()
+++ f = open(os.path.join(self.tempdir, 'platform.ini'), 'w').__enter__()
+++ if 1:
++ f.writelines(self.platform_ini)
+++ f.close()
++ os.chdir(self.tempdir)
++ self._check_version(get_version())
++
++diff -up comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_sources.py.python3 comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_sources.py
++--- comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_sources.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/mozversion/tests/test_sources.py 2014-10-24 11:41:35.525879947 -0600
++@@ -28,31 +28,41 @@ class SourcesTest(unittest.TestCase):
++ self.tempdir = tempfile.mkdtemp()
++
++ self.binary = os.path.join(self.tempdir, 'binary')
++- with open(self.binary, 'w') as f:
+++ f = open(self.binary, 'w')
+++ if 1:
++ f.write('foobar')
++
+++ f.__exit__(0, 0, 0)
++ def tearDown(self):
++ os.chdir(self.cwd)
++ mozfile.remove(self.tempdir)
++
++ def test_sources(self):
++- with open(os.path.join(self.tempdir, 'application.ini'), 'w') as f:
+++ f = open(os.path.join(self.tempdir, 'application.ini'), 'w')
+++ if 1:
++ f.writelines(self.application_ini)
++
+++ f.__exit__(0, 0, 0)
++ sources = os.path.join(self.tempdir, 'sources.xml')
++- with open(sources, 'w') as f:
+++ f = open(sources, 'w').__enter__()
+++ if 1:
++ f.writelines(self.sources_xml)
++
+++ f.__exit__(0, 0, 0)
++ os.chdir(self.tempdir)
++ self._check_version(get_version(sources=sources))
++
++ def test_sources_in_current_directory(self):
++- with open(os.path.join(self.tempdir, 'application.ini'), 'w') as f:
+++ f = open(os.path.join(self.tempdir, 'application.ini'), 'w').__enter__()
+++ if 1:
++ f.writelines(self.application_ini)
++
++- with open(os.path.join(self.tempdir, 'sources.xml'), 'w') as f:
+++ f.close()
+++ f = open(os.path.join(self.tempdir, 'sources.xml'), 'w').__enter__()
+++ if 1:
++ f.writelines(self.sources_xml)
++
+++ f.close()
++ os.chdir(self.tempdir)
++ self._check_version(get_version())
++
++diff -up comm-esr31/mozilla/testing/mozbase/test.py.python3 comm-esr31/mozilla/testing/mozbase/test.py
++--- comm-esr31/mozilla/testing/mozbase/test.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/mozbase/test.py 2014-10-24 11:41:35.525879947 -0600
++@@ -90,7 +90,7 @@ def main(args=sys.argv[1:]):
++ results = TestResultCollection.from_unittest_results(None, unittest_results)
++
++ # exit according to results
++- sys.exit(1 if results.num_failures else 0)
+++ sys.exit(0, 1)[results.num_failures]
++
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/testing/remotecppunittests.py.python3 comm-esr31/mozilla/testing/remotecppunittests.py
++--- comm-esr31/mozilla/testing/remotecppunittests.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/remotecppunittests.py 2014-10-24 11:41:35.525879947 -0600
++@@ -53,7 +53,8 @@ class RemoteCPPUnitTests(cppunittests.CP
++
++ def push_libs(self):
++ if self.options.local_apk:
++- with mozfile.TemporaryDirectory() as tmpdir:
+++ tmpdir = mozfile.TemporaryDirectory().__enter__()
+++ if 1:
++ apk_contents = ZipFile(self.options.local_apk)
++ szip = os.path.join(self.options.local_bin, '..', 'host', 'bin', 'szip')
++ if not os.path.exists(szip):
++@@ -73,6 +74,7 @@ class RemoteCPPUnitTests(cppunittests.CP
++ if szip:
++ out = subprocess.check_output([szip, '-d', file], stderr=subprocess.STDOUT)
++ self.device.pushFile(os.path.join(tmpdir, info.filename), remote_file)
+++ tmpdir.__exit__(0, 0, 0)
++ return
++
++ for file in os.listdir(self.options.local_lib):
++@@ -132,12 +134,14 @@ class RemoteCPPUnitTests(cppunittests.CP
++ returncode = self.device.shell([remote_bin], buf, env=env, cwd=self.remote_home_dir,
++ timeout=cppunittests.CPPUnitTests.TEST_PROC_TIMEOUT)
++ print >> sys.stdout, buf.getvalue()
++- with mozfile.TemporaryDirectory() as tempdir:
+++ tempdir = mozfile.TemporaryDirectory().__enter__()
+++ if 1:
++ self.device.getDirectory(self.remote_home_dir, tempdir)
++ if mozcrash.check_for_crashes(tempdir, symbols_path,
++ test_name=basename):
++ log.testFail("%s | test crashed", basename)
++ return False
+++ tempdir.__exit__(0, 0, 0)
++ result = returncode == 0
++ if not result:
++ log.testFail("%s | test failed with return code %s",
++@@ -182,7 +186,7 @@ class RemoteCPPUnittestOptions(cppunitte
++ self.add_option("--localBinDir", action="store",
++ type = "string", dest = "local_bin",
++ help = "local path to bin directory")
++- defaults["local_bin"] = build_obj.bindir if build_obj is not None else None
+++ defaults["local_bin"] = (None, build_obj.bindir)[build_objis not None]
++
++ self.add_option("--remoteTestRoot", action = "store",
++ type = "string", dest = "remote_test_root",
++@@ -234,7 +238,7 @@ def main():
++ except Exception, e:
++ log.error(str(e))
++ result = False
++- sys.exit(0 if result else 1)
+++ sys.exit((1, 0)[result])
++
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/testing/runcppunittests.py.python3 comm-esr31/mozilla/testing/runcppunittests.py
++--- comm-esr31/mozilla/testing/runcppunittests.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/runcppunittests.py 2014-10-24 11:41:35.526879943 -0600
++@@ -4,11 +4,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++ import sys, os, tempfile, shutil
++ from optparse import OptionParser
++ import mozprocess, mozinfo, mozlog, mozcrash, mozfile
++-from contextlib import contextmanager
+++
++
++ log = mozlog.getLogger('cppunittests')
++
++@@ -32,7 +32,8 @@ class CPPUnitTests(object):
++ """
++ basename = os.path.basename(prog)
++ log.info("Running test %s", basename)
++- with mozfile.TemporaryDirectory() as tempdir:
+++ tempdir = mozfile.TemporaryDirectory().__enter__()
+++ if 1:
++ proc = mozprocess.ProcessHandler([prog],
++ cwd=tempdir,
++ env=env)
++@@ -55,6 +56,7 @@ class CPPUnitTests(object):
++ basename, proc.proc.returncode)
++ return result
++
+++ tempdir.__exit__(0, 0, 0)
++ def build_core_environment(self, env = {}):
++ """
++ Add environment variables likely to be used across all platforms, including remote systems.
++@@ -151,13 +153,15 @@ def extract_unittests_from_args(args, ma
++
++ if manifest_file:
++ skipped_progs.add(os.path.basename(manifest_file))
++- with open(manifest_file) as f:
+++ f = open(manifest_file)
+++ if 1:
++ for line in f:
++ # strip out comment, if any
++ prog = line.split('#')[0]
++ if prog:
++ skipped_progs.add(prog.strip())
++
+++ f.close()
++ for p in args:
++ if os.path.isdir(p):
++ progs.extend([os.path.abspath(os.path.join(p, x)) for x in os.listdir(p) if not x in skipped_progs])
++@@ -184,7 +188,7 @@ def main():
++ except Exception, e:
++ log.error(str(e))
++ result = False
++- sys.exit(0 if result else 1)
+++ sys.exit((1, 0)[result])
++
++ if __name__ == '__main__':
++ main()
++diff -up comm-esr31/mozilla/testing/talos/mach_commands.py.python3 comm-esr31/mozilla/testing/talos/mach_commands.py
++--- comm-esr31/mozilla/testing/talos/mach_commands.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/talos/mach_commands.py 2014-10-24 11:41:35.526879943 -0600
++@@ -4,7 +4,11 @@
++
++ # Integrates Talos mozharness with mach
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import sys
++@@ -64,7 +68,7 @@ class TalosRunner(MozbuildObject):
++ it updates it to the latest version"""
++ try:
++ mercurial = which.which('hg')
++- except which.WhichError as e:
+++ except which.WhichError, e:
++ print("You don't have hg in your PATH: {0}".format(e))
++ raise e
++ clone_cmd = [mercurial, 'clone', '-r', self.mozharness_rev,
++@@ -112,7 +116,7 @@ class TalosRunner(MozbuildObject):
++ try:
++ config_file = open(self.config_file_path, 'wb')
++ config_file.write(json.dumps(self.config))
++- except IOError as e:
+++ except IOError, e:
++ err_str = "Error writing to Talos Mozharness config file {0}:{1}"
++ print(err_str.format(self.config_file_path, str(e)))
++ raise e
++@@ -145,6 +149,6 @@ class MachCommands(MachCommandBase):
++
++ try:
++ return talos.run_test(suite, repo, rev)
++- except Exception as e:
+++ except Exception, e:
++ print(str(e))
++ return 1
++diff -up comm-esr31/mozilla/testing/talos/talos_from_code.py.python3 comm-esr31/mozilla/testing/talos/talos_from_code.py
++--- comm-esr31/mozilla/testing/talos/talos_from_code.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/talos/talos_from_code.py 2014-10-24 11:41:35.526879943 -0600
++@@ -103,7 +103,11 @@ def download_file(url, path="", saveAs=N
++ except Exception, e:
++ print "ERROR: %s" % str(e)
++ sys.exit(1)
++- filename = saveAs if saveAs else get_filename_from_url(url)
+++ filename = None
+++ if saveAs:
+++ filename = saveAs
+++ else:
+++ filename = get_filename_from_url(url)
++ local_file = open(os.path.join(path, filename), 'wb')
++ local_file.write(f.read())
++ local_file.close()
++diff -up comm-esr31/mozilla/testing/tps/tps/phase.py.python3 comm-esr31/mozilla/testing/tps/tps/phase.py
++--- comm-esr31/mozilla/testing/tps/tps/phase.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/tps/tps/phase.py 2014-10-24 11:41:35.526879943 -0600
++@@ -31,7 +31,10 @@ class TPSTestPhase(object):
++
++ @property
++ def status(self):
++- return self._status if self._status else 'unknown'
+++ if self._status:
+++ return self._status
+++ else:
+++ return 'unknown'
++
++ def run(self):
++ # launch Firefox
++diff -up comm-esr31/mozilla/testing/tps/tps/testrunner.py.python3 comm-esr31/mozilla/testing/tps/tps/testrunner.py
++--- comm-esr31/mozilla/testing/tps/tps/testrunner.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/tps/tps/testrunner.py 2014-10-24 11:41:35.527879939 -0600
++@@ -16,8 +16,8 @@ import mozinfo
++ from mozprofile import Profile
++ import mozversion
++
++-from .firefoxrunner import TPSFirefoxRunner
++-from .phase import TPSTestPhase
+++from firefoxrunner import TPSFirefoxRunner
+++from phase import TPSTestPhase
++
++
++ class TempFile(object):
++@@ -118,7 +118,11 @@ class TPSTestRunner(object):
++ resultfile='tps_result.json',
++ testfile=None):
++ self.binary = binary
++- self.config = config if config else {}
+++ self.config = None
+++ if config:
+++ self.config = config
+++ else:
+++ self.config = {}
++ self.debug = debug
++ self.extensions = []
++ self.ignore_unused_engines = ignore_unused_engines
++@@ -149,7 +153,7 @@ class TPSTestRunner(object):
++ @mobile.setter
++ def mobile(self, value):
++ self._mobile = value
++- self.synctype = 'desktop' if not self._mobile else 'mobile'
+++ self.synctype = ('mobile', 'desktop')[not self._mobile]
++
++ def log(self, msg, printToConsole=False):
++ """Appends a string to the logfile"""
++@@ -258,7 +262,8 @@ class TPSTestRunner(object):
++ for f in files:
++ weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
++ if os.access(weavelog, os.F_OK):
++- with open(weavelog, 'r') as fh:
+++ fh = open(weavelog, 'r')
+++ if 1:
++ for line in fh:
++ possible_time = line[0:13]
++ if len(possible_time) == 13 and possible_time.isdigit():
++@@ -269,17 +274,30 @@ class TPSTestRunner(object):
++ formatted, time_ms % 1000, line[14:] ))
++ else:
++ self.log(line)
+++ fh.close()
++ break;
++
++ # grep the log for FF and sync versions
++ f = open(self.logfile)
++ logdata = f.read()
++ match = self.syncVerRe.search(logdata)
++- sync_version = match.group('syncversion') if match else 'unknown'
+++ sync_version = None
+++ if match:
+++ sync_version = match.group('syncversion')
+++ else:
+++ sync_version = 'unknown'
++ match = self.ffVerRe.search(logdata)
++- firefox_version = match.group('ffver') if match else 'unknown'
+++ firefox_version = None
+++ if match:
+++ firefox_version = match.group('ffver')
+++ else:
+++ firefox_version = 'unknown'
++ match = self.ffBuildIDRe.search(logdata)
++- firefox_buildid = match.group('ffbuildid') if match else 'unknown'
+++ firefox_buildid = None
+++ if match:
+++ firefox_buildid = match.group('ffbuildid')
+++ else:
+++ firefox_buildid = 'unknown'
++ f.close()
++ if phase.status == 'PASS':
++ logdata = ''
++@@ -292,7 +310,11 @@ class TPSTestRunner(object):
++ 'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
++ 'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
++ } [phase.status](phase.errline)
++- logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
+++ logstr = None
+++ if result[1]:
+++ logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1]
+++ else:
+++ logstr = ''))
++
++ try:
++ repoinfo = mozversion.get_version(self.binary)
++diff -up comm-esr31/mozilla/testing/xpcshell/mach_commands.py.python3 comm-esr31/mozilla/testing/xpcshell/mach_commands.py
++--- comm-esr31/mozilla/testing/xpcshell/mach_commands.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/xpcshell/mach_commands.py 2014-10-24 11:41:35.527879939 -0600
++@@ -4,7 +4,7 @@
++
++ # Integrates the xpcshell test runner with mach.
++
++-from __future__ import unicode_literals, print_function
+++, print_function
++
++ import mozpack.path
++ import logging
++@@ -154,8 +154,7 @@ class XPCShellRunner(MozbuildObject):
++ 'debugger': debugger,
++ 'debuggerArgs': debuggerArgs,
++ 'debuggerInteractive': debuggerInteractive,
++- 'on_message': (lambda obj, msg: xpcshell.log.info(msg.decode('utf-8', 'replace'))) \
++- if verbose_output else None,
+++ 'on_message': (lambda obj, msg: (None, xpcshell.log.info(msg.decode('utf-8', 'replace'))))[verbose_output],
++ }
++
++ if test_path is not None:
++@@ -320,8 +319,10 @@ class B2GXPCShellRunner(MozbuildObject):
++ 'initial setup will be slow.')
++ return
++
++- with open(busybox_path, 'wb') as f:
+++ f = open(busybox_path, 'wb')
+++ if 1:
++ f.write(data.read())
+++ f.close()
++ return busybox_path
++
++ def run_test(self, test_paths, b2g_home=None, busybox=None,
++@@ -442,6 +443,6 @@ class MachCommands(MachCommandBase):
++
++ try:
++ return xpcshell.run_test(**params)
++- except InvalidTestPathError as e:
+++ except InvalidTestPathError, e:
++ print(e.message)
++ return 1
++diff -up comm-esr31/mozilla/testing/xpcshell/remotexpcshelltests.py.python3 comm-esr31/mozilla/testing/xpcshell/remotexpcshelltests.py
++--- comm-esr31/mozilla/testing/xpcshell/remotexpcshelltests.py.python3 2014-07-17 18:05:51.000000000 -0600
+++++ comm-esr31/mozilla/testing/xpcshell/remotexpcshelltests.py 2014-10-24 11:41:35.527879939 -0600
++@@ -130,10 +130,11 @@ class RemoteXPCShellTestThread(xpcshell.
++ self.timedout = False
++ cmd.insert(1, self.remoteHere)
++ outputFile = "xpcshelloutput"
++- with open(outputFile, 'w+') as f:
+++ f = open(outputFile, 'w+')
+++ if 1:
++ try:
++ self.shellReturnCode = self.device.shell(cmd, f)
++- except devicemanager.DMError as e:
+++ except devicemanager.DMError, e:
++ if self.timedout:
++ # If the test timed out, there is a good chance the SUTagent also
++ # timed out and failed to return a return code, generating a
++@@ -142,6 +143,7 @@ class RemoteXPCShellTestThread(xpcshell.
++ pass
++ else:
++ raise e
+++ f.close()
++ # The device manager may have timed out waiting for xpcshell.
++ # Guard against an accumulation of hung processes by killing
++ # them here. Note also that IPC tests may spawn new instances
++@@ -161,11 +163,13 @@ class RemoteXPCShellTestThread(xpcshell.
++ print "Automation Error: No crash directory (%s) found on remote device" % self.remoteMinidumpDir
++ # Whilst no crash was found, the run should still display as a failure
++ return True
++- with mozfile.TemporaryDirectory() as dumpDir:
+++ dumpDir = mozfile.TemporaryDirectory().__enter__()
+++ if 1:
++ self.device.getDirectory(self.remoteMinidumpDir, dumpDir)
++ crashed = xpcshell.XPCShellTestThread.checkForCrashes(self, dumpDir, symbols_path, test_name)
++ self.device.removeDir(self.remoteMinidumpDir)
++ self.device.mkDir(self.remoteMinidumpDir)
+++ dumpDir.__exit__(0, 0, 0)
++ return crashed
++
++ def communicate(self, proc):
++@@ -333,7 +337,7 @@ class XPCShellRemote(xpcshell.XPCShellTe
++ packageName = self.localAPKContents.read("package-name.txt")
++ if packageName:
++ self.appRoot = self.device.getAppRoot(packageName.strip())
++- except Exception as detail:
+++ except Exception, detail:
++ print "unable to determine app root: " + str(detail)
++ pass
++ return None
++diff -up comm-esr31/mozilla/testing/xpcshell/runxpcshelltests.py.python3 comm-esr31/mozilla/testing/xpcshell/runxpcshelltests.py
++--- comm-esr31/mozilla/testing/xpcshell/runxpcshelltests.py.python3 2014-07-17 18:05:52.000000000 -0600
+++++ comm-esr31/mozilla/testing/xpcshell/runxpcshelltests.py 2014-10-24 11:41:35.528879935 -0600
++@@ -82,7 +82,7 @@ import mozinfo
++ _cleanup_encoding_re = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f\\\\]')
++ def _cleanup_encoding_repl(m):
++ c = m.group(0)
++- return '\\\\' if c == '\\' else '\\x{0:02X}'.format(ord(c))
+++ return ('\\x{0:02X}', '\\\\')[c == '\\'].format(ord(c))
++ def cleanup_encoding(s):
++ """S is either a byte or unicode string. Either way it may
++ contain control characters, unpaired surrogates, reserved code
++@@ -164,7 +164,7 @@ class XPCShellTestThread(Thread):
++ def run(self):
++ try:
++ self.run_test()
++- except Exception as e:
+++ except Exception, e:
++ self.exception = e
++ self.traceback = traceback.format_exc()
++ else:
++@@ -202,9 +202,11 @@ class XPCShellTestThread(Thread):
++ For a given test file and stdout buffer, create a log file.
++ On a remote system we have to fix the test name since it can contain directories.
++ """
++- with open(test_file + ".log", "w") as f:
+++ f = open(test_file + ".log", "w")
+++ if 1:
++ f.write(stdout)
++
+++ f.close()
++ def getReturnCode(self, proc):
++ """
++ Simple wrapper to get the return code for a given process.
++@@ -448,7 +450,11 @@ class XPCShellTestThread(Thread):
++ self.has_failure_output = True
++ return line
++
++- msg = ['%s: ' % line['process'] if 'process' in line else '']
+++ msg = None
+++ if 'process' in line:
+++ msg = ['%s: ' % line['process']
+++ else:
+++ msg = '']
++
++ # Each call to the logger in head.js either specified '_message'
++ # or both 'source_file' and 'diagnostic'. If either of these are
++@@ -463,7 +469,7 @@ class XPCShellTestThread(Thread):
++ line.get('source_file', 'undefined'),
++ line.get('diagnostic', 'undefined')))
++
++- msg.append('\n%s' % line['stack'] if 'stack' in line else '')
+++ msg.append('\n%s' % ('', line['stack']')['stack' in line ])
++ return ''.join(msg)
++
++ def parse_output(self, output):
++@@ -646,16 +652,18 @@ class XPCShellTestThread(Thread):
++ self.clean_temp_dirs(name, stdout)
++ return
++
++- failureType = "TEST-UNEXPECTED-%s" % ("FAIL" if expected else "PASS")
+++ failureType = "TEST-UNEXPECTED-%s" % (("PASS", "FAIL")[expected])
++ message = "%s | %s | test failed (with xpcshell return code: %d)" % (
++ failureType, name, self.getReturnCode(proc))
++ if self.output_lines:
++ message += ", see following log:"
++
++- with LOG_MUTEX:
+++ LOG_MUTEX.__enter__()
+++ if 1:
++ self.log.error(message)
++ self.log_output(self.output_lines)
++
+++ LOG_MUTEX.__exit__(0, 0, 0)
++ self.failCount += 1
++ self.xunit_result["passed"] = False
++
++@@ -666,21 +674,25 @@ class XPCShellTestThread(Thread):
++ }
++
++ if self.failureManifest:
++- with open(self.failureManifest, 'a') as f:
+++ f = open(self.failureManifest, 'a')
+++ if 1:
++ f.write('[%s]\n' % self.test_object['path'])
++ for k, v in self.test_object.items():
++ f.write('%s = %s\n' % (k, v))
++
+++ f.close()
++ else:
++ now = time.time()
++ timeTaken = (now - startTime) * 1000
++ self.xunit_result["time"] = now - startTime
++
++- with LOG_MUTEX:
++- self.log.info("TEST-%s | %s | test passed (time: %.3fms)" % ("PASS" if expected else "KNOWN-FAIL", name, timeTaken))
+++ LOG_MUTEX.__enter__()
+++ if 1:
+++ self.log.info("TEST-%s | %s | test passed (time: %.3fms)" % (("KNOWN-FAIL", "PASS")[expected], name, timeTaken))
++ if self.verbose:
++ self.log_output(self.output_lines)
++
+++ LOG_MUTEX.__exit__(0, 0, 0)
++ self.xunit_result["passed"] = True
++ self.retry = False
++
++@@ -717,11 +729,13 @@ class XPCShellTestThread(Thread):
++ self.clean_temp_dirs(name, stdout)
++ return
++
++- with LOG_MUTEX:
+++ LOG_MUTEX.__enter__()
+++ if 1:
++ message = "TEST-UNEXPECTED-FAIL | %s | Process still running after test!" % name
++ self.log.error(message)
++ self.log_output(self.output_lines)
++
+++ LOG_MUTEX.__exit__(0, 0, 0)
++ self.failCount = 1
++ self.xunit_result["passed"] = False
++ self.xunit_result["failure"] = {
++@@ -768,8 +782,10 @@ class XPCShellTests(object):
++ if unwrapped:
++ def wrap(fn):
++ def wrapped(*args, **kwargs):
++- with LOG_MUTEX:
+++ LOG_MUTEX.__enter__()
+++ if 1:
++ fn(*args, **kwargs)
+++ LOG_MUTEX.__exit__(0, 0, 0)
++ return wrapped
++ setattr(self.log, fun_name, wrap(unwrapped))
++
++diff -up comm-esr31/mozilla/testing/xpcshell/selftest.py.python3 comm-esr31/mozilla/testing/xpcshell/selftest.py
++--- comm-esr31/mozilla/testing/xpcshell/selftest.py.python3 2014-07-17 18:05:52.000000000 -0600
+++++ comm-esr31/mozilla/testing/xpcshell/selftest.py 2014-10-24 11:41:35.528879935 -0600
++@@ -4,7 +4,7 @@
++ # http://creativecommons.org/publicdomain/zero/1.0/
++ #
++
++-from __future__ import with_statement
+++
++ import sys, os, unittest, tempfile, shutil
++ import mozinfo
++
++@@ -243,8 +243,10 @@ class XPCShellTestsTests(unittest.TestCa
++ and return the full path to the file.
++ """
++ fullpath = os.path.join(self.tempdir, name)
++- with open(fullpath, "w") as f:
+++ f = open(fullpath, "w")
+++ if 1:
++ f.write(contents)
+++ f.close()
++ return fullpath
++
++ def writeManifest(self, tests):
++@@ -257,8 +259,7 @@ class XPCShellTestsTests(unittest.TestCa
++ """
++ testlines = []
++ for t in tests:
++- testlines.append("[%s]" % (t if isinstance(t, basestring)
++- else t[0]))
+++ (testlines.append("[%s]" % (t[0], t)[isinstance(t, basestring)]))
++ if isinstance(t, tuple):
++ testlines.extend(t[1:])
++ self.manifest = self.writeFile("xpcshell.ini", """
++@@ -286,7 +287,7 @@ tail =
++ ========
++ %s
++ ========
++-""" % ("passed" if expected else "failed", self.log.getvalue()))
+++""" % (("failed", "passed")[expected], self.log.getvalue()))
++
++ def _assertLog(self, s, expected):
++ l = self.log.getvalue()
++@@ -294,7 +295,7 @@ tail =
++ msg="""Value %s %s in log:
++ ========
++ %s
++-========""" % (s, "expected" if expected else "not expected", l))
+++========""" % (s, ("not expected", "expected")[expected], l))
++
++ def assertInLog(self, s):
++ """
++diff -up comm-esr31/mozilla/toolkit/components/diskspacewatcher/moz.build.python3 comm-esr31/mozilla/toolkit/components/diskspacewatcher/moz.build
++--- comm-esr31/mozilla/toolkit/components/diskspacewatcher/moz.build.python3 2014-07-17 18:05:52.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/components/diskspacewatcher/moz.build 2014-10-24 11:41:35.528879935 -0600
++@@ -14,9 +14,11 @@ EXPORTS += [
++
++ XPIDL_MODULE = 'diskspacewatcher'
++
++-SOURCES = [
+++SOURCES += [
++ 'DiskSpaceWatcher.cpp',
++ ]
+++print("SOURCES CLASS")
+++print(SOURCES.__class__)
++
++ include('/ipc/chromium/chromium-config.mozbuild')
++
++diff -up comm-esr31/mozilla/toolkit/components/telemetry/gen-histogram-data.py.python3 comm-esr31/mozilla/toolkit/components/telemetry/gen-histogram-data.py
++--- comm-esr31/mozilla/toolkit/components/telemetry/gen-histogram-data.py.python3 2014-07-17 18:05:53.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/components/telemetry/gen-histogram-data.py 2014-10-24 11:41:35.528879935 -0600
++@@ -5,7 +5,7 @@
++ # Write out histogram information for C++. The histograms are defined
++ # in a file provided as a command-line argument.
++
++-from __future__ import with_statement
+++
++
++ import sys
++ import histogram_tools
++@@ -64,7 +64,7 @@ def print_array_entry(histogram, name_in
++ % (histogram.low(), histogram.high(),
++ histogram.n_buckets(), histogram.nsITelemetry_kind(),
++ name_index, exp_index,
++- "true" if histogram.extended_statistics_ok() else "false")
+++ ("false", "true")[histogram.extended_statistics_ok()])
++ if cpp_guard:
++ print "#endif"
++
++diff -up comm-esr31/mozilla/toolkit/components/telemetry/histogram_tools.py.python3 comm-esr31/mozilla/toolkit/components/telemetry/histogram_tools.py
++--- comm-esr31/mozilla/toolkit/components/telemetry/histogram_tools.py.python3 2014-07-17 18:05:53.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/components/telemetry/histogram_tools.py 2014-10-24 11:41:35.529879930 -0600
++@@ -2,20 +2,20 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-import json
++ import math
++ import re
++
++-from collections import OrderedDict
+++import simplejson as json
+++from simplejson import OrderedDict
++
++ def table_dispatch(kind, table, body):
++ """Call body with table[kind] if it exists. Raise an error otherwise."""
++ if kind in table:
++ return body(table[kind])
++ else:
++- raise BaseException, "don't know how to handle a histogram of kind %s" % kind
+++ raise Exception, "don't know how to handle a histogram of kind %s" % kind
++
++-class DefinitionException(BaseException):
+++class DefinitionException(Exception):
++ pass
++
++ def check_numeric_limits(dmin, dmax, n_buckets):
++@@ -225,7 +225,10 @@ def from_file(filename):
++ """Return an iterator that provides a sequence of Histograms for
++ the histograms defined in filename.
++ """
++- with open(filename, 'r') as f:
+++ f = open(filename, 'r')
+++ if 1:
++ histograms = json.load(f, object_pairs_hook=OrderedDict)
++ for (name, definition) in histograms.iteritems():
++ yield Histogram(name, definition)
+++ f.close()
+++
++diff -up comm-esr31/mozilla/toolkit/crashreporter/tools/symbolstore.py.python3 comm-esr31/mozilla/toolkit/crashreporter/tools/symbolstore.py
++--- comm-esr31/mozilla/toolkit/crashreporter/tools/symbolstore.py.python3 2014-07-17 18:05:54.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/crashreporter/tools/symbolstore.py 2014-10-24 11:41:35.529879930 -0600
++@@ -388,15 +388,18 @@ class Dumper:
++ """Increments the number of submitted jobs for the specified key file,
++ defined as the original file we processed; note that a single key file
++ can generate up to 1 + len(self.archs) jobs in the Mac case."""
++- with Dumper.jobs_condition:
+++ Dumper.jobs_condition.__enter__()
+++ if 1:
++ self.jobs_record[file_key] += 1
++ Dumper.jobs_condition.notify_all()
++
+++ Dumper.jobs_condition.__exit__(0, 0, 0)
++ def JobFinished(self, file_key):
++ """Decrements the number of submitted jobs for the specified key file,
++ defined as the original file we processed; once the count is back to 0,
++ remove the entry from our record."""
++- with Dumper.jobs_condition:
+++ Dumper.jobs_condition.__enter__()
+++ if 1:
++ self.jobs_record[file_key] -= 1
++
++ if self.jobs_record[file_key] == 0:
++@@ -404,13 +407,16 @@ class Dumper:
++
++ Dumper.jobs_condition.notify_all()
++
+++ Dumper.jobs_condition.__exit__(0, 0, 0)
++ def output(self, dest, output_str):
++ """Writes |output_str| to |dest|, holding |lock|;
++ terminates with a newline."""
++- with Dumper.lock:
+++ Dumper.lock.__enter__()
+++ if 1:
++ dest.write(output_str + "\n")
++ dest.flush()
++
+++ Dumper.lock.__exit__(0, 0, 0)
++ def output_pid(self, dest, output_str):
++ """Debugging output; prepends the pid to the string."""
++ self.output(dest, "%d: %s" % (os.getpid(), output_str))
++@@ -499,9 +505,11 @@ class Dumper:
++ wait for the pool to finish processing them. By default, will close
++ and clear the pool, but for testcases that need multiple runs, pass
++ stop_pool = False."""
++- with Dumper.jobs_condition:
+++ Dumper.jobs_condition.__enter__()
+++ if 1:
++ while len(self.jobs_record) != 0:
++ Dumper.jobs_condition.wait()
+++ Dumper.jobs_condition.__exit__(0, 0, 0)
++ if stop_pool:
++ Dumper.pool.close()
++ Dumper.pool.join()
++@@ -716,7 +724,11 @@ class Dumper_Win32(Dumper):
++ return result
++
++ class Dumper_Linux(Dumper):
++- objcopy = os.environ['OBJCOPY'] if 'OBJCOPY' in os.environ else 'objcopy'
+++ objcopy = None
+++ if 'OBJCOPY' in os.environ:
+++ objcopy = os.environ['OBJCOPY']
+++ else:
+++ objcopy = 'objcopy'
++ def ShouldProcess(self, file):
++ """This function will allow processing of files that are
++ executable, or end with the .so extension, and additionally
++diff -up comm-esr31/mozilla/toolkit/crashreporter/tools/unit-symbolstore.py.python3 comm-esr31/mozilla/toolkit/crashreporter/tools/unit-symbolstore.py
++--- comm-esr31/mozilla/toolkit/crashreporter/tools/unit-symbolstore.py.python3 2014-07-17 18:05:54.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/crashreporter/tools/unit-symbolstore.py 2014-10-24 11:41:35.529879930 -0600
++@@ -68,7 +68,7 @@ class TestExclude(HelperMixin, unittest.
++ processed = []
++ def mock_process_file(filenames):
++ for filename in filenames:
++- processed.append((filename[len(self.test_dir):] if filename.startswith(self.test_dir) else filename).replace('\\', '/'))
+++ processed.append(((filename, filename[len(self.test_dir):]).replace('\\')[filename.startswith(self.test_dir)], '/'))
++ return True
++ self.add_test_files(add_extension(["foo", "bar", "abc/xyz", "abc/fooxyz", "def/asdf", "def/xyzfoo"]))
++ d = symbolstore.GetPlatformSpecificDumper(dump_syms="dump_syms",
++@@ -89,7 +89,7 @@ class TestExclude(HelperMixin, unittest.
++ processed = []
++ def mock_process_file(filenames):
++ for filename in filenames:
++- processed.append((filename[len(self.test_dir):] if filename.startswith(self.test_dir) else filename).replace('\\', '/'))
+++ processed.append(((filename, filename[len(self.test_dir):]).replace('\\')[filename.startswith(self.test_dir)], '/'))
++ return True
++ self.add_test_files(add_extension(["foo", "bar", "abc/foo", "abc/bar", "def/foo", "def/bar"]))
++ d = symbolstore.GetPlatformSpecificDumper(dump_syms="dump_syms",
++@@ -165,7 +165,7 @@ class TestCopyDebugUniversal(HelperMixin
++ """
++ copied = []
++ def mock_copy_debug(filename, debug_file, guid):
++- copied.append(filename[len(self.symbol_dir):] if filename.startswith(self.symbol_dir) else filename)
+++ copied.append((filename, filename[len(self.symbol_dir):])[filename.startswith(self.symbol_dir)])
++ self.add_test_files(add_extension(["foo"]))
++ self.stdouts.append(mock_dump_syms("X" * 33, add_extension(["foo"])[0]))
++ self.stdouts.append(mock_dump_syms("Y" * 33, add_extension(["foo"])[0]))
++diff -up comm-esr31/mozilla/toolkit/devtools/acorn/moz.build.python3 comm-esr31/mozilla/toolkit/devtools/acorn/moz.build
++--- comm-esr31/mozilla/toolkit/devtools/acorn/moz.build.python3 2014-07-17 18:05:54.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/devtools/acorn/moz.build 2014-10-24 11:41:35.529879930 -0600
++@@ -1,15 +1,15 @@
++-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
++-# vim: set filetype=python:
++-# This Source Code Form is subject to the terms of the Mozilla Public
++-# License, v. 2.0. If a copy of the MPL was not distributed with this
++-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
++-
++-XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
++-
++-JS_MODULES_PATH = 'modules/devtools/acorn'
++-
++-EXTRA_JS_MODULES += [
++- 'acorn.js',
++- 'acorn_loose.js',
++- 'walk.js',
++-]
+++# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+++# vim: set filetype=python:
+++# This Source Code Form is subject to the terms of the Mozilla Public
+++# License, v. 2.0. If a copy of the MPL was not distributed with this
+++# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+++
+++XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
+++
+++JS_MODULES_PATH = 'modules/devtools/acorn'
+++
+++EXTRA_JS_MODULES += [
+++ 'acorn.js',
+++ 'acorn_loose.js',
+++ 'walk.js',
+++]
++diff -up comm-esr31/mozilla/toolkit/mozapps/extensions/internal/moz.build.python3 comm-esr31/mozilla/toolkit/mozapps/extensions/internal/moz.build
++--- comm-esr31/mozilla/toolkit/mozapps/extensions/internal/moz.build.python3 2014-07-17 18:05:55.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/mozapps/extensions/internal/moz.build 2014-10-24 11:41:35.529879930 -0600
++@@ -1,31 +1,31 @@
++-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
++-# vim: set filetype=python:
++-# This Source Code Form is subject to the terms of the Mozilla Public
++-# License, v. 2.0. If a copy of the MPL was not distributed with this
++-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
++-
++-JS_MODULES_PATH = 'modules/addons'
++-
++-EXTRA_JS_MODULES += [
++- 'AddonLogging.jsm',
++- 'AddonRepository.jsm',
++- 'AddonRepository_SQLiteMigrator.jsm',
++- 'AddonUpdateChecker.jsm',
++- 'Content.js',
++- 'LightweightThemeImageOptimizer.jsm',
++- 'PluginProvider.jsm',
++- 'SpellCheckDictionaryBootstrap.js',
++-]
++-
++-EXTRA_PP_JS_MODULES += [
++- 'XPIProvider.jsm',
++- 'XPIProviderUtils.js',
++-]
++-
++-# This is used in multiple places, so is defined here to avoid it getting
++-# out of sync.
++-DEFINES['MOZ_EXTENSIONS_DB_SCHEMA'] = 16
++-
++-# Additional debugging info is exposed in debug builds
++-if CONFIG['MOZ_EM_DEBUG']:
++- DEFINES['MOZ_EM_DEBUG'] = 1
+++# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+++# vim: set filetype=python:
+++# This Source Code Form is subject to the terms of the Mozilla Public
+++# License, v. 2.0. If a copy of the MPL was not distributed with this
+++# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+++
+++JS_MODULES_PATH = 'modules/addons'
+++
+++EXTRA_JS_MODULES += [
+++ 'AddonLogging.jsm',
+++ 'AddonRepository.jsm',
+++ 'AddonRepository_SQLiteMigrator.jsm',
+++ 'AddonUpdateChecker.jsm',
+++ 'Content.js',
+++ 'LightweightThemeImageOptimizer.jsm',
+++ 'PluginProvider.jsm',
+++ 'SpellCheckDictionaryBootstrap.js',
+++]
+++
+++EXTRA_PP_JS_MODULES += [
+++ 'XPIProvider.jsm',
+++ 'XPIProviderUtils.js',
+++]
+++
+++# This is used in multiple places, so is defined here to avoid it getting
+++# out of sync.
+++DEFINES['MOZ_EXTENSIONS_DB_SCHEMA'] = 16
+++
+++# Additional debugging info is exposed in debug builds
+++if CONFIG['MOZ_EM_DEBUG']:
+++ DEFINES['MOZ_EM_DEBUG'] = 1
++diff -up comm-esr31/mozilla/toolkit/mozapps/installer/dozip.py.python3 comm-esr31/mozilla/toolkit/mozapps/installer/dozip.py
++--- comm-esr31/mozilla/toolkit/mozapps/installer/dozip.py.python3 2014-07-17 18:05:55.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/mozapps/installer/dozip.py 2014-10-24 11:41:35.530879926 -0600
++@@ -29,7 +29,8 @@ def main(args):
++
++ jarrer = Jarrer(optimize=False)
++
++- with errors.accumulate():
+++ errors.accumulate().__enter__()
+++ if 1:
++ finder = FileFinder(args.base_dir)
++ for i in args.input:
++ path = mozpath.relpath(i, args.base_dir)
++@@ -38,5 +39,6 @@ def main(args):
++ jarrer.copy(args.zip)
++
++
+++ errors.accumulate().__exit__(0, 0, 0)
++ if __name__ == '__main__':
++ main(sys.argv[1:])
++diff -up comm-esr31/mozilla/toolkit/mozapps/installer/find-dupes.py.python3 comm-esr31/mozilla/toolkit/mozapps/installer/find-dupes.py
++--- comm-esr31/mozilla/toolkit/mozapps/installer/find-dupes.py.python3 2014-07-17 18:05:55.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/mozapps/installer/find-dupes.py 2014-10-24 11:41:35.530879926 -0600
++@@ -3,9 +3,9 @@
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++ import sys
++-import hashlib
+++import md5
++ from mozpack.packager.unpack import UnpackFinder
++-from collections import OrderedDict
+++from ordereddict import OrderedDict
++
++ '''
++ Find files duplicated in a given packaged directory, independently of its
++@@ -17,7 +17,7 @@ def find_dupes(source):
++ md5s = OrderedDict()
++ for p, f in UnpackFinder(source):
++ content = f.open().read()
++- m = hashlib.md5(content).digest()
+++ m = md5.md5(content).digest()
++ if not m in md5s:
++ md5s[m] = (len(content), [])
++ md5s[m][1].append(p)
++@@ -26,7 +26,7 @@ def find_dupes(source):
++ for m, (size, paths) in md5s.iteritems():
++ if len(paths) > 1:
++ print 'Duplicates %d bytes%s:' % (size,
++- ' (%d times)' % (len(paths) - 1) if len(paths) > 2 else '')
+++ ' (%d times)' % ((0, len(paths) - 1)[len(paths) > 2]))
++ print ''.join(' %s\n' % p for p in paths)
++ total += (len(paths) - 1) * size
++ num_dupes += 1
++diff -up comm-esr31/mozilla/toolkit/mozapps/installer/informulate.py.python3 comm-esr31/mozilla/toolkit/mozapps/installer/informulate.py
++--- comm-esr31/mozilla/toolkit/mozapps/installer/informulate.py.python3 2014-07-17 18:05:55.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/mozapps/installer/informulate.py 2014-10-24 11:41:35.530879926 -0600
++@@ -37,10 +37,12 @@ def main():
++ all_key_value_pairs = dict([(x.lower(), buildconfig.substs[x]) for x in important_substitutions])
++ all_key_value_pairs.update(parse_cmdline(sys.argv[2:]))
++
++- with open(sys.argv[1], "w+") as f:
+++ f = open(sys.argv[1], "w+")
+++ if 1:
++ json.dump(all_key_value_pairs, f, indent=2, sort_keys=True)
++ f.write('\n')
++
++
+++ f.close()
++ if __name__=="__main__":
++ main()
++diff -up comm-esr31/mozilla/toolkit/mozapps/installer/packager.py.python3 comm-esr31/mozilla/toolkit/mozapps/installer/packager.py
++--- comm-esr31/mozilla/toolkit/mozapps/installer/packager.py.python3 2014-07-17 18:05:55.000000000 -0600
+++++ comm-esr31/mozilla/toolkit/mozapps/installer/packager.py 2014-10-24 11:41:35.530879926 -0600
++@@ -2,6 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
+++from rhrebase import all, any
++ from mozpack.packager.formats import (
++ FlatFormatter,
++ JarFormatter,
++@@ -316,7 +317,8 @@ def main():
++ elif not buildconfig.substs['CROSS_COMPILE']:
++ launcher.tooldir = buildconfig.substs['LIBXUL_DIST']
++
++- with errors.accumulate():
+++ errors.accumulate()
+++ if 1:
++ finder_args = dict(
++ minify=args.minify,
++ minify_js=args.minify_js,
++@@ -353,6 +355,7 @@ def main():
++ preprocess(removals_in, removals, defines)
++ copier.add(mozpack.path.join(binpath, 'removed-files'), removals)
++
+++ #errors.accumulate().__exit__(0, 0, 0)
++ # shlibsign libraries
++ if launcher.can_launch():
++ for lib in SIGN_LIBS:
++diff -up comm-esr31/mozilla/tools/docs/conf.py.python3 comm-esr31/mozilla/tools/docs/conf.py
++--- comm-esr31/mozilla/tools/docs/conf.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/docs/conf.py 2014-10-24 11:41:35.530879926 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++ import re
++diff -up comm-esr31/mozilla/tools/docs/mach_commands.py.python3 comm-esr31/mozilla/tools/docs/mach_commands.py
++--- comm-esr31/mozilla/tools/docs/mach_commands.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/docs/mach_commands.py 2014-10-24 11:41:35.531879922 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++diff -up comm-esr31/mozilla/tools/docs/moztreedocs/__init__.py.python3 comm-esr31/mozilla/tools/docs/moztreedocs/__init__.py
++--- comm-esr31/mozilla/tools/docs/moztreedocs/__init__.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/docs/moztreedocs/__init__.py 2014-10-24 11:41:35.531879922 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import os
++
++@@ -98,9 +98,11 @@ class SphinxManager(object):
++ m.populate_registry(copier)
++ copier.copy(stage_dir)
++
++- with open(self._index_path, 'rb') as fh:
+++ fh = open(self._index_path, 'rb')
+++ if 1:
++ data = fh.read()
++
+++ fh.__exit__(0, 0, 0)
++ indexes = ['%s/index' % p for p in sorted(self._trees.keys())]
++ indexes = '\n '.join(indexes)
++
++@@ -109,5 +111,8 @@ class SphinxManager(object):
++ packages = '\n '.join(sorted(packages))
++ data = data.format(indexes=indexes, python_packages=packages)
++
++- with open(os.path.join(stage_dir, 'index.rst'), 'wb') as fh:
+++ fh = open(os.path.join(stage_dir, 'index.rst'), 'wb').__enter__()
+++ if 1:
++ fh.write(data)
+++ fh.close()
+++
++diff -up comm-esr31/mozilla/tools/mach_commands.py.python3 comm-esr31/mozilla/tools/mach_commands.py
++--- comm-esr31/mozilla/tools/mach_commands.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/mach_commands.py 2014-10-24 11:41:35.531879922 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import sys
++ import os
++@@ -247,8 +247,10 @@ class PastebinProvider(object):
++
++ if file:
++ try:
++- with open(file, 'r') as f:
+++ f = open(file, 'r')
+++ if 1:
++ content = f.read()
+++ f.close()
++ # TODO: Use mime-types instead of extensions; suprocess('file <f_name>')
++ # Guess File-type based on file extension
++ extension = file.split('.')[-1]
++@@ -344,7 +346,7 @@ class FormatProvider(MachCommandBase):
++ if not clang_format_diff:
++ return 1
++
++- except urllib2.HTTPError as e:
+++ except urllib2.HTTPError, e:
++ print("HTTP error {0}: {1}".format(e.code, e.reason))
++ return 1
++
++@@ -360,7 +362,7 @@ class FormatProvider(MachCommandBase):
++ diff_process = Popen(["filterdiff", "--include=*.h", "--include=*.cpp",
++ "--exclude-from-file=.clang-format-ignore"],
++ stdin=git_process.stdout, stdout=PIPE)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno == errno.ENOENT:
++ print("Can't find filterdiff. Please install patchutils.")
++ else:
++@@ -387,9 +389,11 @@ class FormatProvider(MachCommandBase):
++ print("Downloading {0} to {1}".format(u, target))
++ data = urllib2.urlopen(url=u).read()
++ temp = target + ".tmp"
++- with open(temp, "wb") as fh:
+++ fh = open(temp, "wb")
+++ if 1:
++ fh.write(data)
++ fh.close()
+++ fh.close()
++ os.chmod(temp, os.stat(temp).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
++ os.rename(temp, target)
++ return target
++diff -up comm-esr31/mozilla/tools/mercurial/hgsetup/config.py.python3 comm-esr31/mozilla/tools/mercurial/hgsetup/config.py
++--- comm-esr31/mozilla/tools/mercurial/hgsetup/config.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/mercurial/hgsetup/config.py 2014-10-24 11:41:35.531879922 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this,
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ from configobj import ConfigObj
++ import re
++diff -up comm-esr31/mozilla/tools/mercurial/hgsetup/wizard.py.python3 comm-esr31/mozilla/tools/mercurial/hgsetup/wizard.py
++--- comm-esr31/mozilla/tools/mercurial/hgsetup/wizard.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/mercurial/hgsetup/wizard.py 2014-10-24 11:41:35.531879922 -0600
++@@ -2,7 +2,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this,
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import unicode_literals
+++
++
++ import difflib
++ import errno
++@@ -19,7 +19,7 @@ from mozversioncontrol.repoupdate import
++ update_git_repo,
++ )
++
++-from .config import (
+++from config import (
++ HOST_FINGERPRINTS,
++ MercurialConfig,
++ )
++@@ -102,13 +102,13 @@ class MercurialSetupWizard(object):
++ def run(self, config_paths):
++ try:
++ os.makedirs(self.ext_dir)
++- except OSError as e:
+++ except OSError, e:
++ if e.errno != errno.EEXIST:
++ raise
++
++ try:
++ hg = which.which('hg')
++- except which.WhichError as e:
+++ except which.WhichError, e:
++ print(e)
++ print('Try running |mach bootstrap| to ensure your environment is '
++ 'up to date.')
++@@ -116,7 +116,7 @@ class MercurialSetupWizard(object):
++
++ try:
++ c = MercurialConfig(config_paths)
++- except ConfigObjError as e:
+++ except ConfigObjError, e:
++ print('Error importing existing Mercurial config!\n'
++ '%s\n'
++ 'If using quotes, they must wrap the entire string.' % e)
++@@ -212,9 +212,11 @@ class MercurialSetupWizard(object):
++
++ config_path = c.config_path
++ if os.path.exists(config_path):
++- with open(config_path, 'rt') as fh:
+++ fh = open(config_path, 'rt')
+++ if 1:
++ old_lines = [line.rstrip() for line in fh.readlines()]
++
+++ fh.close()
++ diff = list(difflib.unified_diff(old_lines, new_lines,
++ 'hgrc.old', 'hgrc.new'))
++
++@@ -228,8 +230,10 @@ class MercurialSetupWizard(object):
++ print('')
++
++ if self._prompt_yn('Would you like me to update your hgrc file'):
++- with open(config_path, 'wt') as fh:
+++ fh = open(config_path, 'wt')
+++ if 1:
++ c.write(fh)
+++ fh.close()
++ print('Wrote changes to %s.' % config_path)
++ else:
++ print('hgrc changes not written to file. I would have '
++diff -up comm-esr31/mozilla/tools/mercurial/mach_commands.py.python3 comm-esr31/mozilla/tools/mercurial/mach_commands.py
++--- comm-esr31/mozilla/tools/mercurial/mach_commands.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/mercurial/mach_commands.py 2014-10-24 11:41:35.532879918 -0600
++@@ -2,7 +2,11 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this,
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import print_function, unicode_literals
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
++
++ import os
++ import sys
++@@ -34,7 +38,9 @@ class VersionControlCommands(object):
++ # Touch a file so we can periodically prompt to update extensions.
++ state_path = os.path.join(self._context.state_dir,
++ 'mercurial/setup.lastcheck')
++- with open(state_path, 'a'):
+++ open(state_path, 'a').__enter__()
+++ if 1:
++ os.utime(state_path, None)
++
+++ open(state_path, 'a').__exit__(0, 0, 0)
++ return result
++diff -up comm-esr31/mozilla/tools/profiler/LulElf.cpp.python3 comm-esr31/mozilla/tools/profiler/LulElf.cpp
++--- comm-esr31/mozilla/tools/profiler/LulElf.cpp.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/profiler/LulElf.cpp 2014-10-24 11:41:35.532879918 -0600
++@@ -69,6 +69,11 @@
++ #include "LulElfInt.h"
++ #include "LulMainInt.h"
++
+++#ifndef NT_GNU_BUILD_ID
+++#define NT_GNU_BUILD_ID 3
+++#endif
+++
+++
++
++ #if defined(LUL_PLAT_arm_android) && !defined(SHT_ARM_EXIDX)
++ // bionic and older glibsc don't define it
++diff -up comm-esr31/mozilla/tools/rb/fix_stack_using_bpsyms.py.python3 comm-esr31/mozilla/tools/rb/fix_stack_using_bpsyms.py
++--- comm-esr31/mozilla/tools/rb/fix_stack_using_bpsyms.py.python3 2014-07-17 18:05:56.000000000 -0600
+++++ comm-esr31/mozilla/tools/rb/fix_stack_using_bpsyms.py 2014-10-24 11:41:35.532879918 -0600
++@@ -4,7 +4,7 @@
++ # License, v. 2.0. If a copy of the MPL was not distributed with this
++ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++-from __future__ import with_statement
+++
++
++ import sys
++ import os
++@@ -30,7 +30,8 @@ class SymbolFile:
++ addrs = [] # list of addresses, which will be sorted once we're done initializing
++ funcs = {} # hash: address --> (function name + possible file/line)
++ files = {} # hash: filenum (string) --> prettified filename ready to have a line number appended
++- with open(fn) as f:
+++ f = open(fn)
+++ if 1:
++ for line in f:
++ line = line.rstrip()
++ # http://code.google.com/p/google-breakpad/wiki/SymbolFiles
++@@ -61,6 +62,7 @@ class SymbolFile:
++ funcs[rva] = name
++ addrs.append(rva)
++ # skip everything else
+++ f.close()
++ #print "Loaded %d functions from symbol file %s" % (len(funcs), os.path.basename(fn))
++ self.addrs = sorted(addrs)
++ self.funcs = funcs
++diff -up comm-esr31/mozilla/xpcom/idl-parser/header.py.python3 comm-esr31/mozilla/xpcom/idl-parser/header.py
++--- comm-esr31/mozilla/xpcom/idl-parser/header.py.python3 2014-07-17 18:05:57.000000000 -0600
+++++ comm-esr31/mozilla/xpcom/idl-parser/header.py 2014-10-24 11:41:35.532879918 -0600
++@@ -159,7 +159,8 @@ forward_decl = """class %(name)s; /* for
++
++ def idl_basename(f):
++ """returns the base name of a file with the last extension stripped"""
++- return os.path.basename(f).rpartition('.')[0]
+++ return ".".join(os.path.basename(f).split('.')[:-1])
+++ #return os.path.basename(f).rpartition('.')[0]
++
++ def print_header(idl, fd, filename):
++ fd.write(header % {'filename': filename,
++@@ -333,11 +334,18 @@ def write_interface(iface, fd):
++
++ fd.write(" %s = 0;\n" % attributeAsNative(a, True))
++ if a.infallible:
+++ a_args = ''
+++ if a.implicit_jscontext:
+++ a_args = 'JSContext* cx'
+++ a_argnames = ''
+++ if a.implicit_jscontext:
+++ a.implicit_jscontext = 'cx, '
++ fd.write(attr_infallible_tmpl %
+++
++ {'realtype': a.realtype.nativeType('in'),
++ 'nativename': attributeNativeName(a, getter=True),
++- 'args': '' if not a.implicit_jscontext else 'JSContext* cx',
++- 'argnames': '' if not a.implicit_jscontext else 'cx, '})
+++ 'args': a_args,
+++ 'argnames': a_argnames})
++
++ if not a.readonly:
++ fd.write(" %s = 0;\n" % attributeAsNative(a, False))
++@@ -486,7 +494,11 @@ if __name__ == '__main__':
++ o.add_option('--regen', action='store_true', dest='regen', default=False,
++ help="Regenerate IDL Parser cache")
++ options, args = o.parse_args()
++- file = args[0] if args else None
+++ file = None
+++ if args:
+++ file = args[0]
+++ else:
+++ file = None
++
++ if options.cachedir is not None:
++ if not os.path.isdir(options.cachedir):
++diff -up comm-esr31/mozilla/xpcom/idl-parser/typelib.py.python3 comm-esr31/mozilla/xpcom/idl-parser/typelib.py
++--- comm-esr31/mozilla/xpcom/idl-parser/typelib.py.python3 2014-07-17 18:05:57.000000000 -0600
+++++ comm-esr31/mozilla/xpcom/idl-parser/typelib.py 2014-10-24 11:41:35.533879913 -0600
++@@ -260,7 +260,11 @@ if __name__ == '__main__':
++ o.add_option('--regen', action='store_true', dest='regen', default=False,
++ help="Regenerate IDL Parser cache")
++ options, args = o.parse_args()
++- file = args[0] if args else None
+++ file = None
+++ if args:
+++ file = args[0]
+++ else:
+++ file = None
++
++ if options.cachedir is not None:
++ if not os.path.isdir(options.cachedir):
++diff -up comm-esr31/mozilla/xpcom/typelib/xpt/tools/xpt.py.python3 comm-esr31/mozilla/xpcom/typelib/xpt/tools/xpt.py
++--- comm-esr31/mozilla/xpcom/typelib/xpt/tools/xpt.py.python3 2014-07-17 18:05:57.000000000 -0600
+++++ comm-esr31/mozilla/xpcom/typelib/xpt/tools/xpt.py 2014-10-24 11:41:35.533879913 -0600
++@@ -65,8 +65,9 @@ InterfaceType() - construct a new
++
++ """
++
++-from __future__ import with_statement
+++
++ import os, sys
+++import mystruct
++ import struct
++ import operator
++
++@@ -102,7 +103,7 @@ class Type(object):
++ this class directly. Rather, use one of its subclasses.
++
++ """
++- _prefixdescriptor = struct.Struct(">B")
+++ _prefixdescriptor = mystruct.Struct(">B")
++ Tags = enum(
++ # The first 18 entries are SimpleTypeDescriptor
++ 'int8',
++@@ -263,7 +264,7 @@ class InterfaceType(Type):
++ (InterfaceTypeDescriptor from the typelib specification.)
++
++ """
++- _descriptor = struct.Struct(">H")
+++ _descriptor = mystruct.Struct(">H")
++
++ def __init__(self, iface, pointer=True, **kwargs):
++ if not pointer:
++@@ -315,7 +316,7 @@ class InterfaceIsType(Type):
++ typelib specification.)
++
++ """
++- _descriptor = struct.Struct(">B")
+++ _descriptor = mystruct.Struct(">B")
++ _cache = {}
++
++ def __init__(self, param_index, pointer=True, **kwargs):
++@@ -364,7 +365,7 @@ class ArrayType(Type):
++ (ArrayTypeDescriptor from the typelib specification.)
++
++ """
++- _descriptor = struct.Struct(">BB")
+++ _descriptor = mystruct.Struct(">BB")
++
++ def __init__(self, element_type, size_is_arg_num, length_is_arg_num,
++ pointer=True, **kwargs):
++@@ -414,7 +415,7 @@ class StringWithSizeType(Type):
++ from the typelib specification.)
++
++ """
++- _descriptor = struct.Struct(">BB")
+++ _descriptor = mystruct.Struct(">BB")
++
++ def __init__(self, size_is_arg_num, length_is_arg_num,
++ pointer=True, **kwargs):
++@@ -461,7 +462,7 @@ class WideStringWithSizeType(Type):
++ (WideStringWithSizeTypeDescriptor from the typelib specification.)
++
++ """
++- _descriptor = struct.Struct(">BB")
+++ _descriptor = mystruct.Struct(">BB")
++
++ def __init__(self, size_is_arg_num, length_is_arg_num,
++ pointer=True, **kwargs):
++@@ -507,7 +508,7 @@ class Param(object):
++ (ParamDescriptor from the typelib specification.)
++
++ """
++- _descriptorstart = struct.Struct(">B")
+++ _descriptorstart = mystruct.Struct(">B")
++
++ def __init__(self, type, in_=True, out=False, retval=False,
++ shared=False, dipper=False, optional=False):
++@@ -626,7 +627,7 @@ class Method(object):
++ (MethodDescriptor from the typelib specification.)
++
++ """
++- _descriptorstart = struct.Struct(">BIB")
+++ _descriptorstart = mystruct.Struct(">BIB")
++
++ def __init__(self, name, result,
++ params=[], getter=False, setter=False, notxpcom=False,
++@@ -767,7 +768,7 @@ class Constant(object):
++ (ConstantDesciptor from the typelib specification.)
++
++ """
++- _descriptorstart = struct.Struct(">I")
+++ _descriptorstart = mystruct.Struct(">I")
++ # Actual value is restricted to this set of types
++ #XXX: the spec lies, the source allows a bunch more
++ # http://hg.mozilla.org/mozilla-central/annotate/9c85f9aaec8c/xpcom/typelib/xpt/src/xpt_struct.c#l689
++@@ -801,7 +802,7 @@ class Constant(object):
++ if isinstance(t, SimpleType) and t.tag in Constant.typemap:
++ tt = Constant.typemap[t.tag]
++ start = data_pool + offset - 1
++- (val,) = struct.unpack_from(tt, map, start)
+++ (val,) = mystruct.unpack_from(tt, map, start)
++ offset += struct.calcsize(tt)
++ c = Constant(name, t, val)
++ return c, offset
++@@ -840,8 +841,8 @@ class Interface(object):
++ (InterfaceDescriptor from the typelib specification.)
++
++ """
++- _direntry = struct.Struct(">16sIII")
++- _descriptorstart = struct.Struct(">HH")
+++ _direntry = mystruct.Struct(">16sIII")
+++ _descriptorstart = mystruct.Struct(">HH")
++
++ UNRESOLVED_IID = "00000000-0000-0000-0000-000000000000"
++
++@@ -919,14 +920,14 @@ class Interface(object):
++ self.methods.append(m)
++ # Read constants
++ start = data_pool + offset - 1
++- (num_constants, ) = struct.unpack_from(">H", map, start)
+++ (num_constants, ) = mystruct.unpack_from(">H", map, start)
++ offset = offset + struct.calcsize(">H")
++ for i in range(num_constants):
++ c, offset = Constant.read(typelib, map, data_pool, offset)
++ self.constants.append(c)
++ # Read flags
++ start = data_pool + offset - 1
++- (flags, ) = struct.unpack_from(">B", map, start)
+++ (flags, ) = mystruct.unpack_from(">B", map, start)
++ offset = offset + struct.calcsize(">B")
++ # only the first two bits are flags
++ flags &= 0xE0
++@@ -1011,7 +1012,7 @@ class Typelib(object):
++ or the static Typelib.read method may be called to read one from a file.
++
++ """
++- _header = struct.Struct(">16sBBHIII")
+++ _header = mystruct.Struct(">16sBBHIII")
++
++ def __init__(self, version=TYPELIB_VERSION, interfaces=[], annotations=[]):
++ """
++@@ -1067,10 +1068,12 @@ class Typelib(object):
++ expected_size = None
++ if isinstance(input_file, basestring):
++ filename = input_file
++- with open(input_file, "rb") as f:
+++ f = open(input_file, "rb")
+++ if 1:
++ st = os.fstat(f.fileno())
++ data = f.read(st.st_size)
++ expected_size = st.st_size
+++ f.__exit__(0, 0, 0)
++ else:
++ data = input_file.read()
++
++@@ -1096,7 +1099,7 @@ class Typelib(object):
++ # make a half-hearted attempt to read Annotations,
++ # since XPIDL doesn't produce any anyway.
++ start = Typelib._header.size
++- (anno, ) = struct.unpack_from(">B", data, start)
+++ (anno, ) = mystruct.unpack_from(">B", data, start)
++ islast = anno & 0x80
++ tag = anno & 0x7F
++ if tag == 0: # EmptyAnnotation
++@@ -1184,8 +1187,10 @@ class Typelib(object):
++ """
++ self._sanityCheck()
++ if isinstance(output_file, basestring):
++- with open(output_file, "wb") as f:
+++ f = open(output_file, "wb")
+++ if 1:
++ self.writefd(f)
+++ f.close()
++ else:
++ self.writefd(output_file)
++
diff --cc pango-backport.patch
index 0000000,0000000..d38f542
new file mode 100644
--- /dev/null
+++ b/pango-backport.patch
@@@ -1,0 -1,0 +1,60 @@@
++diff -up mozilla-aurora/configure.in.pango-backport mozilla-aurora/configure.in
++--- mozilla-aurora/configure.in.pango-backport 2014-05-06 13:17:17.000000000 +0200
+++++ mozilla-aurora/configure.in 2014-08-07 12:07:28.000000000 +0200
++@@ -60,7 +60,7 @@ dnl ====================================
++ GLIB_VERSION=1.2.0
++ PERL_VERSION=5.006
++ CAIRO_VERSION=1.10
++-PANGO_VERSION=1.22.0
+++PANGO_VERSION=1.14.0
++ GTK2_VERSION=2.10.0
++ GTK3_VERSION=3.0.0
++ WINDRES_VERSION=2.14.90
++diff -up mozilla-aurora/configure.pango-backport mozilla-aurora/configure
++--- mozilla-aurora/configure.pango-backport 2014-08-07 12:08:55.000000000 +0200
+++++ mozilla-aurora/configure 2014-08-07 12:09:20.000000000 +0200
++@@ -1296,7 +1296,7 @@ NSS_VERSION=3
++ GLIB_VERSION=1.2.0
++ PERL_VERSION=5.006
++ CAIRO_VERSION=1.10
++-PANGO_VERSION=1.22.0
+++PANGO_VERSION=1.14.0
++ GTK2_VERSION=2.10.0
++ GTK3_VERSION=3.0.0
++ WINDRES_VERSION=2.14.90
++diff -up mozilla-aurora/gfx/thebes/gfxPlatform.cpp.pango-backport mozilla-aurora/gfx/thebes/gfxPlatform.cpp
++--- mozilla-aurora/gfx/thebes/gfxPlatform.cpp.pango-backport 2014-05-19 11:43:50.000000000 +0200
+++++ mozilla-aurora/gfx/thebes/gfxPlatform.cpp 2014-08-07 12:07:28.000000000 +0200
++@@ -530,6 +530,14 @@ gfxPlatform::~gfxPlatform()
++ cairo_debug_reset_static_data();
++ #endif
++ #endif
+++
+++#if 0
+++ // It would be nice to do this (although it might need to be after
+++ // the cairo shutdown that happens in ~gfxPlatform). It even looks
+++ // idempotent. But it has fatal assertions that fire if stuff is
+++ // leaked, and we hit them.
+++ FcFini();
+++#endif
++ }
++
++ bool
++diff -up mozilla-aurora/gfx/thebes/gfxPlatformGtk.cpp.pango-backport mozilla-aurora/gfx/thebes/gfxPlatformGtk.cpp
++--- mozilla-aurora/gfx/thebes/gfxPlatformGtk.cpp.pango-backport 2014-05-06 13:17:14.000000000 +0200
+++++ mozilla-aurora/gfx/thebes/gfxPlatformGtk.cpp 2014-08-07 12:07:28.000000000 +0200
++@@ -77,6 +77,14 @@ gfxPlatformGtk::~gfxPlatformGtk()
++ sFontconfigUtils = nullptr;
++
++ gfxPangoFontGroup::Shutdown();
+++
+++#if 0
+++ // It would be nice to do this (although it might need to be after
+++ // the cairo shutdown that happens in ~gfxPlatform). It even looks
+++ // idempotent. But it has fatal assertions that fire if stuff is
+++ // leaked, and we hit them.
+++ FcFini();
+++#endif
++ }
++
++ already_AddRefed<gfxASurface>
diff --cc rebase-dir.patch
index 0000000,0000000..42af1f6
new file mode 100644
--- /dev/null
+++ b/rebase-dir.patch
@@@ -1,0 -1,0 +1,7577 @@@
++diff -up mozilla-aurora/rebase/abc.py.rebase-dir mozilla-aurora/rebase/abc.py
++--- mozilla-aurora/rebase/abc.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/abc.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,182 @@
+++# Copyright 2007 Google, Inc. All Rights Reserved.
+++# Licensed to PSF under a Contributor Agreement.
+++
+++"""Abstract Base Classes (ABCs) according to PEP 3119."""
+++
+++
+++# Instance of old-style class
+++class _C: pass
+++_InstanceType = type(_C())
+++
+++
+++def abstractmethod(funcobj):
+++ """A decorator indicating abstract methods.
+++
+++ Requires that the metaclass is ABCMeta or derived from it. A
+++ class that has a metaclass derived from ABCMeta cannot be
+++ instantiated unless all of its abstract methods are overridden.
+++ The abstract methods can be called using any of the normal
+++ 'super' call mechanisms.
+++
+++ Usage:
+++
+++ class C:
+++ __metaclass__ = ABCMeta
+++ @abstractmethod
+++ def my_abstract_method(self, ...):
+++ ...
+++ """
+++ funcobj.__isabstractmethod__ = True
+++ return funcobj
+++
+++
+++class abstractproperty(property):
+++ """A decorator indicating abstract properties.
+++
+++ Requires that the metaclass is ABCMeta or derived from it. A
+++ class that has a metaclass derived from ABCMeta cannot be
+++ instantiated unless all of its abstract properties are overridden.
+++ The abstract properties can be called using any of the normal
+++ 'super' call mechanisms.
+++
+++ Usage:
+++
+++ class C:
+++ __metaclass__ = ABCMeta
+++ @abstractproperty
+++ def my_abstract_property(self):
+++ ...
+++
+++ This defines a read-only property; you can also define a read-write
+++ abstract property using the 'long' form of property declaration:
+++
+++ class C:
+++ __metaclass__ = ABCMeta
+++ def getx(self): ...
+++ def setx(self, value): ...
+++ x = abstractproperty(getx, setx)
+++ """
+++ __isabstractmethod__ = True
+++
+++
+++class ABCMeta(type):
+++
+++ """Metaclass for defining Abstract Base Classes (ABCs).
+++
+++ Use this metaclass to create an ABC. An ABC can be subclassed
+++ directly, and then acts as a mix-in class. You can also register
+++ unrelated concrete classes (even built-in classes) and unrelated
+++ ABCs as 'virtual subclasses' -- these and their descendants will
+++ be considered subclasses of the registering ABC by the built-in
+++ issubclass() function, but the registering ABC won't show up in
+++ their MRO (Method Resolution Order) nor will method
+++ implementations defined by the registering ABC be callable (not
+++ even via super()).
+++
+++ """
+++
+++ # A global counter that is incremented each time a class is
+++ # registered as a virtual subclass of anything. It forces the
+++ # negative cache to be cleared before its next use.
+++ _abc_invalidation_counter = 0
+++
+++ def __new__(mcls, name, bases, namespace):
+++ cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
+++ # Compute set of abstract method names
+++ abstracts = set(name
+++ for name, value in namespace.items()
+++ if getattr(value, "__isabstractmethod__", False))
+++ for base in bases:
+++ for name in getattr(base, "__abstractmethods__", set()):
+++ value = getattr(cls, name, None)
+++ if getattr(value, "__isabstractmethod__", False):
+++ abstracts.add(name)
+++ cls.__abstractmethods__ = frozenset(abstracts)
+++ # Set up inheritance registry
+++ cls._abc_registry = set()
+++ cls._abc_cache = set()
+++ cls._abc_negative_cache = set()
+++ cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+++ return cls
+++
+++ def register(cls, subclass):
+++ """Register a virtual subclass of an ABC."""
+++ if not isinstance(cls, type):
+++ raise TypeError("Can only register classes")
+++ if issubclass(subclass, cls):
+++ return # Already a subclass
+++ # Subtle: test for cycles *after* testing for "already a subclass";
+++ # this means we allow X.register(X) and interpret it as a no-op.
+++ if issubclass(cls, subclass):
+++ # This would create a cycle, which is bad for the algorithm below
+++ raise RuntimeError("Refusing to create an inheritance cycle")
+++ cls._abc_registry.add(subclass)
+++ ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
+++
+++ def _dump_registry(cls, file=None):
+++ """Debug helper to print the ABC registry."""
+++ print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__)
+++ print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter
+++ for name in sorted(cls.__dict__.keys()):
+++ if name.startswith("_abc_"):
+++ value = getattr(cls, name)
+++ print >> file, "%s: %r" % (name, value)
+++
+++ def __instancecheck__(cls, instance):
+++ """Override for isinstance(instance, cls)."""
+++ # Inline the cache checking when it's simple.
+++ subclass = getattr(instance, '__class__', None)
+++ if subclass in cls._abc_cache:
+++ return True
+++ subtype = type(instance)
+++ # Old-style instances
+++ if subtype is _InstanceType:
+++ subtype = subclass
+++ if subtype is subclass or subclass is None:
+++ if (cls._abc_negative_cache_version ==
+++ ABCMeta._abc_invalidation_counter and
+++ subtype in cls._abc_negative_cache):
+++ return False
+++ # Fall back to the subclass check.
+++ return cls.__subclasscheck__(subtype)
+++ return (cls.__subclasscheck__(subclass) or
+++ cls.__subclasscheck__(subtype))
+++
+++ def __subclasscheck__(cls, subclass):
+++ """Override for issubclass(subclass, cls)."""
+++ # Check cache
+++ if subclass in cls._abc_cache:
+++ return True
+++ # Check negative cache; may have to invalidate
+++ if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
+++ # Invalidate the negative cache
+++ cls._abc_negative_cache = set()
+++ cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+++ elif subclass in cls._abc_negative_cache:
+++ return False
+++ # Check the subclass hook
+++ ok = cls.__subclasshook__(subclass)
+++ if ok is not NotImplemented:
+++ assert isinstance(ok, bool)
+++ if ok:
+++ cls._abc_cache.add(subclass)
+++ else:
+++ cls._abc_negative_cache.add(subclass)
+++ return ok
+++ # Check if it's a direct subclass
+++ if cls in getattr(subclass, '__mro__', ()):
+++ cls._abc_cache.add(subclass)
+++ return True
+++ # Check if it's a subclass of a registered class (recursive)
+++ for rcls in cls._abc_registry:
+++ if issubclass(subclass, rcls):
+++ cls._abc_cache.add(subclass)
+++ return True
+++ # Check if it's a subclass of a subclass (recursive)
+++ for scls in cls.__subclasses__():
+++ if issubclass(subclass, scls):
+++ cls._abc_cache.add(subclass)
+++ return True
+++ # No dice; update negative cache
+++ cls._abc_negative_cache.add(subclass)
+++ return False
++diff -up mozilla-aurora/rebase/argparse.py.rebase-dir mozilla-aurora/rebase/argparse.py
++--- mozilla-aurora/rebase/argparse.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/argparse.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,4724 @@
+++# Author: Steven J. Bethard <steven.bethard at gmail.com>.
+++
+++"""Command-line parsing library
+++
+++This module is an optparse-inspired command-line parsing library that:
+++
+++ - handles both optional and positional arguments
+++ - produces highly informative usage messages
+++ - supports parsers that dispatch to sub-parsers
+++
+++The following is a simple usage example that sums integers from the
+++command-line and writes the result to a file::
+++
+++ parser = argparse.ArgumentParser(
+++ description='sum the integers at the command line')
+++ parser.add_argument(
+++ 'integers', metavar='int', nargs='+', type=int,
+++ help='an integer to be summed')
+++ parser.add_argument(
+++ '--log', default=sys.stdout, type=argparse.FileType('w'),
+++ help='the file where the sum should be written')
+++ args = parser.parse_args()
+++ args.log.write('%s' % sum(args.integers))
+++ args.log.close()
+++
+++The module contains the following public classes:
+++
+++ - ArgumentParser -- The main entry point for command-line parsing. As the
+++ example above shows, the add_argument() method is used to populate
+++ the parser with actions for optional and positional arguments. Then
+++ the parse_args() method is invoked to convert the args at the
+++ command-line into an object with attributes.
+++
+++ - ArgumentError -- The exception raised by ArgumentParser objects when
+++ there are errors with the parser's actions. Errors raised while
+++ parsing the command-line are caught by ArgumentParser and emitted
+++ as command-line messages.
+++
+++ - FileType -- A factory for defining types of files to be created. As the
+++ example above shows, instances of FileType are typically passed as
+++ the type= argument of add_argument() calls.
+++
+++ - Action -- The base class for parser actions. Typically actions are
+++ selected by passing strings like 'store_true' or 'append_const' to
+++ the action= argument of add_argument(). However, for greater
+++ customization of ArgumentParser actions, subclasses of Action may
+++ be defined and passed as the action= argument.
+++
+++ - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
+++ ArgumentDefaultsHelpFormatter -- Formatter classes which
+++ may be passed as the formatter_class= argument to the
+++ ArgumentParser constructor. HelpFormatter is the default,
+++ RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
+++ not to change the formatting for help text, and
+++ ArgumentDefaultsHelpFormatter adds information about argument defaults
+++ to the help.
+++
+++All other classes in this module are considered implementation details.
+++(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
+++considered public as object names -- the API of the formatter objects is
+++still considered an implementation detail.)
+++"""
+++
+++__version__ = '1.2.1'
+++__all__ = [
+++ 'ArgumentParser',
+++ 'ArgumentError',
+++ 'ArgumentTypeError',
+++ 'FileType',
+++ 'HelpFormatter',
+++ 'ArgumentDefaultsHelpFormatter',
+++ 'RawDescriptionHelpFormatter',
+++ 'RawTextHelpFormatter',
+++ 'Namespace',
+++ 'Action',
+++ 'ONE_OR_MORE',
+++ 'OPTIONAL',
+++ 'PARSER',
+++ 'REMAINDER',
+++ 'SUPPRESS',
+++ 'ZERO_OR_MORE',
+++]
+++
+++
+++import copy as _copy
+++import os as _os
+++import re as _re
+++import sys as _sys
+++import textwrap as _textwrap
+++
+++from gettext import gettext as _
+++
+++try:
+++ set
+++except NameError:
+++ # for python < 2.4 compatibility (sets module is there since 2.3):
+++ from sets import Set as set
+++
+++try:
+++ basestring
+++except NameError:
+++ basestring = str
+++
+++try:
+++ sorted
+++except NameError:
+++ # for python < 2.4 compatibility:
+++ def sorted(iterable, reverse=False):
+++ result = list(iterable)
+++ result.sort()
+++ if reverse:
+++ result.reverse()
+++ return result
+++
+++
+++def _callable(obj):
+++ return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
+++
+++
+++SUPPRESS = '==SUPPRESS=='
+++
+++OPTIONAL = '?'
+++ZERO_OR_MORE = '*'
+++ONE_OR_MORE = '+'
+++PARSER = 'A...'
+++REMAINDER = '...'
+++_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
+++
+++# =============================
+++# Utility functions and classes
+++# =============================
+++
+++class _AttributeHolder(object):
+++ """Abstract base class that provides __repr__.
+++
+++ The __repr__ method returns a string in the format::
+++ ClassName(attr=name, attr=name, ...)
+++ The attributes are determined either by a class-level attribute,
+++ '_kwarg_names', or by inspecting the instance __dict__.
+++ """
+++
+++ def __repr__(self):
+++ type_name = type(self).__name__
+++ arg_strings = []
+++ for arg in self._get_args():
+++ arg_strings.append(repr(arg))
+++ for name, value in self._get_kwargs():
+++ arg_strings.append('%s=%r' % (name, value))
+++ return '%s(%s)' % (type_name, ', '.join(arg_strings))
+++
+++ def _get_kwargs(self):
+++ return sorted(self.__dict__.items())
+++
+++ def _get_args(self):
+++ return []
+++
+++
+++def _ensure_value(namespace, name, value):
+++ if getattr(namespace, name, None) is None:
+++ setattr(namespace, name, value)
+++ return getattr(namespace, name)
+++
+++
+++# ===============
+++# Formatting Help
+++# ===============
+++
+++class HelpFormatter(object):
+++ """Formatter for generating usage messages and argument help strings.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def __init__(self,
+++ prog,
+++ indent_increment=2,
+++ max_help_position=24,
+++ width=None):
+++
+++ # default setting for width
+++ if width is None:
+++ try:
+++ width = int(_os.environ['COLUMNS'])
+++ except (KeyError, ValueError):
+++ width = 80
+++ width -= 2
+++
+++ self._prog = prog
+++ self._indent_increment = indent_increment
+++ self._max_help_position = max_help_position
+++ self._width = width
+++
+++ self._current_indent = 0
+++ self._level = 0
+++ self._action_max_length = 0
+++
+++ self._root_section = self._Section(self, None)
+++ self._current_section = self._root_section
+++
+++ self._whitespace_matcher = _re.compile(r'\s+')
+++ self._long_break_matcher = _re.compile(r'\n\n\n+')
+++
+++ # ===============================
+++ # Section and indentation methods
+++ # ===============================
+++ def _indent(self):
+++ self._current_indent += self._indent_increment
+++ self._level += 1
+++
+++ def _dedent(self):
+++ self._current_indent -= self._indent_increment
+++ assert self._current_indent >= 0, 'Indent decreased below 0.'
+++ self._level -= 1
+++
+++ class _Section(object):
+++
+++ def __init__(self, formatter, parent, heading=None):
+++ self.formatter = formatter
+++ self.parent = parent
+++ self.heading = heading
+++ self.items = []
+++
+++ def format_help(self):
+++ # format the indented section
+++ if self.parent is not None:
+++ self.formatter._indent()
+++ join = self.formatter._join_parts
+++ for func, args in self.items:
+++ func(*args)
+++ item_help = join([func(*args) for func, args in self.items])
+++ if self.parent is not None:
+++ self.formatter._dedent()
+++
+++ # return nothing if the section was empty
+++ if not item_help:
+++ return ''
+++
+++ # add the heading if the section was non-empty
+++ if self.heading is not SUPPRESS and self.heading is not None:
+++ current_indent = self.formatter._current_indent
+++ heading = '%*s%s:\n' % (current_indent, '', self.heading)
+++ else:
+++ heading = ''
+++
+++ # join the section-initial newline, the heading and the help
+++ return join(['\n', heading, item_help, '\n'])
+++
+++ def _add_item(self, func, args):
+++ self._current_section.items.append((func, args))
+++
+++ # ========================
+++ # Message building methods
+++ # ========================
+++ def start_section(self, heading):
+++ self._indent()
+++ section = self._Section(self, self._current_section, heading)
+++ self._add_item(section.format_help, [])
+++ self._current_section = section
+++
+++ def end_section(self):
+++ self._current_section = self._current_section.parent
+++ self._dedent()
+++
+++ def add_text(self, text):
+++ if text is not SUPPRESS and text is not None:
+++ self._add_item(self._format_text, [text])
+++
+++ def add_usage(self, usage, actions, groups, prefix=None):
+++ if usage is not SUPPRESS:
+++ args = usage, actions, groups, prefix
+++ self._add_item(self._format_usage, args)
+++
+++ def add_argument(self, action):
+++ if action.help is not SUPPRESS:
+++
+++ # find all invocations
+++ get_invocation = self._format_action_invocation
+++ invocations = [get_invocation(action)]
+++ for subaction in self._iter_indented_subactions(action):
+++ invocations.append(get_invocation(subaction))
+++
+++ # update the maximum item length
+++ invocation_length = max([len(s) for s in invocations])
+++ action_length = invocation_length + self._current_indent
+++ self._action_max_length = max(self._action_max_length,
+++ action_length)
+++
+++ # add the item to the list
+++ self._add_item(self._format_action, [action])
+++
+++ def add_arguments(self, actions):
+++ for action in actions:
+++ self.add_argument(action)
+++
+++ # =======================
+++ # Help-formatting methods
+++ # =======================
+++ def format_help(self):
+++ help = self._root_section.format_help()
+++ if help:
+++ help = self._long_break_matcher.sub('\n\n', help)
+++ help = help.strip('\n') + '\n'
+++ return help
+++
+++ def _join_parts(self, part_strings):
+++ return ''.join([part
+++ for part in part_strings
+++ if part and part is not SUPPRESS])
+++
+++ def _format_usage(self, usage, actions, groups, prefix):
+++ if prefix is None:
+++ prefix = _('usage: ')
+++
+++ # if usage is specified, use that
+++ if usage is not None:
+++ usage = usage % dict(prog=self._prog)
+++
+++ # if no optionals or positionals are available, usage is just prog
+++ elif usage is None and not actions:
+++ usage = '%(prog)s' % dict(prog=self._prog)
+++
+++ # if optionals and positionals are available, calculate usage
+++ elif usage is None:
+++ prog = '%(prog)s' % dict(prog=self._prog)
+++
+++ # split optionals from positionals
+++ optionals = []
+++ positionals = []
+++ for action in actions:
+++ if action.option_strings:
+++ optionals.append(action)
+++ else:
+++ positionals.append(action)
+++
+++ # build full usage string
+++ format = self._format_actions_usage
+++ action_usage = format(optionals + positionals, groups)
+++ usage = ' '.join([s for s in [prog, action_usage] if s])
+++
+++ # wrap the usage parts if it's too long
+++ text_width = self._width - self._current_indent
+++ if len(prefix) + len(usage) > text_width:
+++
+++ # break usage into wrappable parts
+++ part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
+++ opt_usage = format(optionals, groups)
+++ pos_usage = format(positionals, groups)
+++ opt_parts = _re.findall(part_regexp, opt_usage)
+++ pos_parts = _re.findall(part_regexp, pos_usage)
+++ assert ' '.join(opt_parts) == opt_usage
+++ assert ' '.join(pos_parts) == pos_usage
+++
+++ # helper for wrapping lines
+++ def get_lines(parts, indent, prefix=None):
+++ lines = []
+++ line = []
+++ if prefix is not None:
+++ line_len = len(prefix) - 1
+++ else:
+++ line_len = len(indent) - 1
+++ for part in parts:
+++ if line_len + 1 + len(part) > text_width:
+++ lines.append(indent + ' '.join(line))
+++ line = []
+++ line_len = len(indent) - 1
+++ line.append(part)
+++ line_len += len(part) + 1
+++ if line:
+++ lines.append(indent + ' '.join(line))
+++ if prefix is not None:
+++ lines[0] = lines[0][len(indent):]
+++ return lines
+++
+++ # if prog is short, follow it with optionals or positionals
+++ if len(prefix) + len(prog) <= 0.75 * text_width:
+++ indent = ' ' * (len(prefix) + len(prog) + 1)
+++ if opt_parts:
+++ lines = get_lines([prog] + opt_parts, indent, prefix)
+++ lines.extend(get_lines(pos_parts, indent))
+++ elif pos_parts:
+++ lines = get_lines([prog] + pos_parts, indent, prefix)
+++ else:
+++ lines = [prog]
+++
+++ # if prog is long, put it on its own line
+++ else:
+++ indent = ' ' * len(prefix)
+++ parts = opt_parts + pos_parts
+++ lines = get_lines(parts, indent)
+++ if len(lines) > 1:
+++ lines = []
+++ lines.extend(get_lines(opt_parts, indent))
+++ lines.extend(get_lines(pos_parts, indent))
+++ lines = [prog] + lines
+++
+++ # join lines into usage
+++ usage = '\n'.join(lines)
+++
+++ # prefix with 'usage:'
+++ return '%s%s\n\n' % (prefix, usage)
+++
+++ def _format_actions_usage(self, actions, groups):
+++ # find group indices and identify actions in groups
+++ group_actions = set()
+++ inserts = {}
+++ for group in groups:
+++ try:
+++ start = actions.index(group._group_actions[0])
+++ except ValueError:
+++ continue
+++ else:
+++ end = start + len(group._group_actions)
+++ if actions[start:end] == group._group_actions:
+++ for action in group._group_actions:
+++ group_actions.add(action)
+++ if not group.required:
+++ if start in inserts:
+++ inserts[start] += ' ['
+++ else:
+++ inserts[start] = '['
+++ inserts[end] = ']'
+++ else:
+++ if start in inserts:
+++ inserts[start] += ' ('
+++ else:
+++ inserts[start] = '('
+++ inserts[end] = ')'
+++ for i in range(start + 1, end):
+++ inserts[i] = '|'
+++
+++ # collect all actions format strings
+++ parts = []
+++ for i, action in enumerate(actions):
+++
+++ # suppressed arguments are marked with None
+++ # remove | separators for suppressed arguments
+++ if action.help is SUPPRESS:
+++ parts.append(None)
+++ if inserts.get(i) == '|':
+++ inserts.pop(i)
+++ elif inserts.get(i + 1) == '|':
+++ inserts.pop(i + 1)
+++
+++ # produce all arg strings
+++ elif not action.option_strings:
+++ part = self._format_args(action, action.dest)
+++
+++ # if it's in a group, strip the outer []
+++ if action in group_actions:
+++ if part[0] == '[' and part[-1] == ']':
+++ part = part[1:-1]
+++
+++ # add the action string to the list
+++ parts.append(part)
+++
+++ # produce the first way to invoke the option in brackets
+++ else:
+++ option_string = action.option_strings[0]
+++
+++ # if the Optional doesn't take a value, format is:
+++ # -s or --long
+++ if action.nargs == 0:
+++ part = '%s' % option_string
+++
+++ # if the Optional takes a value, format is:
+++ # -s ARGS or --long ARGS
+++ else:
+++ default = action.dest.upper()
+++ args_string = self._format_args(action, default)
+++ part = '%s %s' % (option_string, args_string)
+++
+++ # make it look optional if it's not required or in a group
+++ if not action.required and action not in group_actions:
+++ part = '[%s]' % part
+++
+++ # add the action string to the list
+++ parts.append(part)
+++
+++ # insert things at the necessary indices
+++ for i in sorted(inserts, reverse=True):
+++ parts[i:i] = [inserts[i]]
+++
+++ # join all the action items with spaces
+++ text = ' '.join([item for item in parts if item is not None])
+++
+++ # clean up separators for mutually exclusive groups
+++ open = r'[\[(]'
+++ close = r'[\])]'
+++ text = _re.sub(r'(%s) ' % open, r'\1', text)
+++ text = _re.sub(r' (%s)' % close, r'\1', text)
+++ text = _re.sub(r'%s *%s' % (open, close), r'', text)
+++ text = _re.sub(r'\(([^|]*)\)', r'\1', text)
+++ text = text.strip()
+++
+++ # return the text
+++ return text
+++
+++ def _format_text(self, text):
+++ if '%(prog)' in text:
+++ text = text % dict(prog=self._prog)
+++ text_width = self._width - self._current_indent
+++ indent = ' ' * self._current_indent
+++ return self._fill_text(text, text_width, indent) + '\n\n'
+++
+++ def _format_action(self, action):
+++ # determine the required width and the entry label
+++ help_position = min(self._action_max_length + 2,
+++ self._max_help_position)
+++ help_width = self._width - help_position
+++ action_width = help_position - self._current_indent - 2
+++ action_header = self._format_action_invocation(action)
+++
+++ # ho nelp; start on same line and add a final newline
+++ if not action.help:
+++ tup = self._current_indent, '', action_header
+++ action_header = '%*s%s\n' % tup
+++
+++ # short action name; start on the same line and pad two spaces
+++ elif len(action_header) <= action_width:
+++ tup = self._current_indent, '', action_width, action_header
+++ action_header = '%*s%-*s ' % tup
+++ indent_first = 0
+++
+++ # long action name; start on the next line
+++ else:
+++ tup = self._current_indent, '', action_header
+++ action_header = '%*s%s\n' % tup
+++ indent_first = help_position
+++
+++ # collect the pieces of the action help
+++ parts = [action_header]
+++
+++ # if there was help for the action, add lines of help text
+++ if action.help:
+++ help_text = self._expand_help(action)
+++ help_lines = self._split_lines(help_text, help_width)
+++ parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
+++ for line in help_lines[1:]:
+++ parts.append('%*s%s\n' % (help_position, '', line))
+++
+++ # or add a newline if the description doesn't end with one
+++ elif not action_header.endswith('\n'):
+++ parts.append('\n')
+++
+++ # if there are any sub-actions, add their help as well
+++ for subaction in self._iter_indented_subactions(action):
+++ parts.append(self._format_action(subaction))
+++
+++ # return a single string
+++ return self._join_parts(parts)
+++
+++ def _format_action_invocation(self, action):
+++ if not action.option_strings:
+++ metavar, = self._metavar_formatter(action, action.dest)(1)
+++ return metavar
+++
+++ else:
+++ parts = []
+++
+++ # if the Optional doesn't take a value, format is:
+++ # -s, --long
+++ if action.nargs == 0:
+++ parts.extend(action.option_strings)
+++
+++ # if the Optional takes a value, format is:
+++ # -s ARGS, --long ARGS
+++ else:
+++ default = action.dest.upper()
+++ args_string = self._format_args(action, default)
+++ for option_string in action.option_strings:
+++ parts.append('%s %s' % (option_string, args_string))
+++
+++ return ', '.join(parts)
+++
+++ def _metavar_formatter(self, action, default_metavar):
+++ if action.metavar is not None:
+++ result = action.metavar
+++ elif action.choices is not None:
+++ choice_strs = [str(choice) for choice in action.choices]
+++ result = '{%s}' % ','.join(choice_strs)
+++ else:
+++ result = default_metavar
+++
+++ def format(tuple_size):
+++ if isinstance(result, tuple):
+++ return result
+++ else:
+++ return (result, ) * tuple_size
+++ return format
+++
+++ def _format_args(self, action, default_metavar):
+++ get_metavar = self._metavar_formatter(action, default_metavar)
+++ if action.nargs is None:
+++ result = '%s' % get_metavar(1)
+++ elif action.nargs == OPTIONAL:
+++ result = '[%s]' % get_metavar(1)
+++ elif action.nargs == ZERO_OR_MORE:
+++ result = '[%s [%s ...]]' % get_metavar(2)
+++ elif action.nargs == ONE_OR_MORE:
+++ result = '%s [%s ...]' % get_metavar(2)
+++ elif action.nargs == REMAINDER:
+++ result = '...'
+++ elif action.nargs == PARSER:
+++ result = '%s ...' % get_metavar(1)
+++ else:
+++ formats = ['%s' for _ in range(action.nargs)]
+++ result = ' '.join(formats) % get_metavar(action.nargs)
+++ return result
+++
+++ def _expand_help(self, action):
+++ params = dict(vars(action), prog=self._prog)
+++ for name in list(params):
+++ if params[name] is SUPPRESS:
+++ del params[name]
+++ for name in list(params):
+++ if hasattr(params[name], '__name__'):
+++ params[name] = params[name].__name__
+++ if params.get('choices') is not None:
+++ choices_str = ', '.join([str(c) for c in params['choices']])
+++ params['choices'] = choices_str
+++ return self._get_help_string(action) % params
+++
+++ def _iter_indented_subactions(self, action):
+++ try:
+++ get_subactions = action._get_subactions
+++ except AttributeError:
+++ pass
+++ else:
+++ self._indent()
+++ for subaction in get_subactions():
+++ yield subaction
+++ self._dedent()
+++
+++ def _split_lines(self, text, width):
+++ text = self._whitespace_matcher.sub(' ', text).strip()
+++ return _textwrap.wrap(text, width)
+++
+++ def _fill_text(self, text, width, indent):
+++ text = self._whitespace_matcher.sub(' ', text).strip()
+++ return _textwrap.fill(text, width, initial_indent=indent,
+++ subsequent_indent=indent)
+++
+++ def _get_help_string(self, action):
+++ return action.help
+++
+++
+++class RawDescriptionHelpFormatter(HelpFormatter):
+++ """Help message formatter which retains any formatting in descriptions.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _fill_text(self, text, width, indent):
+++ return ''.join([indent + line for line in text.splitlines(True)])
+++
+++
+++class RawTextHelpFormatter(RawDescriptionHelpFormatter):
+++ """Help message formatter which retains formatting of all help text.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _split_lines(self, text, width):
+++ return text.splitlines()
+++
+++
+++class ArgumentDefaultsHelpFormatter(HelpFormatter):
+++ """Help message formatter which adds default values to argument help.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _get_help_string(self, action):
+++ help = action.help
+++ if '%(default)' not in action.help:
+++ if action.default is not SUPPRESS:
+++ defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
+++ if action.option_strings or action.nargs in defaulting_nargs:
+++ help += ' (default: %(default)s)'
+++ return help
+++
+++
+++# =====================
+++# Options and Arguments
+++# =====================
+++
+++def _get_action_name(argument):
+++ if argument is None:
+++ return None
+++ elif argument.option_strings:
+++ return '/'.join(argument.option_strings)
+++ elif argument.metavar not in (None, SUPPRESS):
+++ return argument.metavar
+++ elif argument.dest not in (None, SUPPRESS):
+++ return argument.dest
+++ else:
+++ return None
+++
+++
+++class ArgumentError(Exception):
+++ """An error from creating or using an argument (optional or positional).
+++
+++ The string value of this exception is the message, augmented with
+++ information about the argument that caused it.
+++ """
+++
+++ def __init__(self, argument, message):
+++ self.argument_name = _get_action_name(argument)
+++ self.message = message
+++
+++ def __str__(self):
+++ if self.argument_name is None:
+++ format = '%(message)s'
+++ else:
+++ format = 'argument %(argument_name)s: %(message)s'
+++ return format % dict(message=self.message,
+++ argument_name=self.argument_name)
+++
+++
+++class ArgumentTypeError(Exception):
+++ """An error from trying to convert a command line string to a type."""
+++ pass
+++
+++
+++# ==============
+++# Action classes
+++# ==============
+++
+++class Action(_AttributeHolder):
+++ """Information about how to convert command line strings to Python objects.
+++
+++ Action objects are used by an ArgumentParser to represent the information
+++ needed to parse a single argument from one or more strings from the
+++ command line. The keyword arguments to the Action constructor are also
+++ all attributes of Action instances.
+++
+++ Keyword Arguments:
+++
+++ - option_strings -- A list of command-line option strings which
+++ should be associated with this action.
+++
+++ - dest -- The name of the attribute to hold the created object(s)
+++
+++ - nargs -- The number of command-line arguments that should be
+++ consumed. By default, one argument will be consumed and a single
+++ value will be produced. Other values include:
+++ - N (an integer) consumes N arguments (and produces a list)
+++ - '?' consumes zero or one arguments
+++ - '*' consumes zero or more arguments (and produces a list)
+++ - '+' consumes one or more arguments (and produces a list)
+++ Note that the difference between the default and nargs=1 is that
+++ with the default, a single value will be produced, while with
+++ nargs=1, a list containing a single value will be produced.
+++
+++ - const -- The value to be produced if the option is specified and the
+++ option uses an action that takes no values.
+++
+++ - default -- The value to be produced if the option is not specified.
+++
+++ - type -- The type which the command-line arguments should be converted
+++ to, should be one of 'string', 'int', 'float', 'complex' or a
+++ callable object that accepts a single string argument. If None,
+++ 'string' is assumed.
+++
+++ - choices -- A container of values that should be allowed. If not None,
+++ after a command-line argument has been converted to the appropriate
+++ type, an exception will be raised if it is not a member of this
+++ collection.
+++
+++ - required -- True if the action must always be specified at the
+++ command line. This is only meaningful for optional command-line
+++ arguments.
+++
+++ - help -- The help string describing the argument.
+++
+++ - metavar -- The name to be used for the option's argument with the
+++ help string. If None, the 'dest' value will be used as the name.
+++ """
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ self.option_strings = option_strings
+++ self.dest = dest
+++ self.nargs = nargs
+++ self.const = const
+++ self.default = default
+++ self.type = type
+++ self.choices = choices
+++ self.required = required
+++ self.help = help
+++ self.metavar = metavar
+++
+++ def _get_kwargs(self):
+++ names = [
+++ 'option_strings',
+++ 'dest',
+++ 'nargs',
+++ 'const',
+++ 'default',
+++ 'type',
+++ 'choices',
+++ 'help',
+++ 'metavar',
+++ ]
+++ return [(name, getattr(self, name)) for name in names]
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ raise NotImplementedError(_('.__call__() not defined'))
+++
+++
+++class _StoreAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ if nargs == 0:
+++ raise ValueError('nargs for store actions must be > 0; if you '
+++ 'have nothing to store, actions such as store '
+++ 'true or store const may be more appropriate')
+++ if const is not None and nargs != OPTIONAL:
+++ raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+++ super(_StoreAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=nargs,
+++ const=const,
+++ default=default,
+++ type=type,
+++ choices=choices,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ setattr(namespace, self.dest, values)
+++
+++
+++class _StoreConstAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ const,
+++ default=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ super(_StoreConstAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ const=const,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ setattr(namespace, self.dest, self.const)
+++
+++
+++class _StoreTrueAction(_StoreConstAction):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=False,
+++ required=False,
+++ help=None):
+++ super(_StoreTrueAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ const=True,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++
+++class _StoreFalseAction(_StoreConstAction):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=True,
+++ required=False,
+++ help=None):
+++ super(_StoreFalseAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ const=False,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++
+++class _AppendAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ if nargs == 0:
+++ raise ValueError('nargs for append actions must be > 0; if arg '
+++ 'strings are not supplying the value to append, '
+++ 'the append const action may be more appropriate')
+++ if const is not None and nargs != OPTIONAL:
+++ raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+++ super(_AppendAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=nargs,
+++ const=const,
+++ default=default,
+++ type=type,
+++ choices=choices,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ items = _copy.copy(_ensure_value(namespace, self.dest, []))
+++ items.append(values)
+++ setattr(namespace, self.dest, items)
+++
+++
+++class _AppendConstAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ const,
+++ default=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ super(_AppendConstAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ const=const,
+++ default=default,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ items = _copy.copy(_ensure_value(namespace, self.dest, []))
+++ items.append(self.const)
+++ setattr(namespace, self.dest, items)
+++
+++
+++class _CountAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=None,
+++ required=False,
+++ help=None):
+++ super(_CountAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ new_count = _ensure_value(namespace, self.dest, 0) + 1
+++ setattr(namespace, self.dest, new_count)
+++
+++
+++class _HelpAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest=SUPPRESS,
+++ default=SUPPRESS,
+++ help=None):
+++ super(_HelpAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ default=default,
+++ nargs=0,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ parser.print_help()
+++ parser.exit()
+++
+++
+++class _VersionAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ version=None,
+++ dest=SUPPRESS,
+++ default=SUPPRESS,
+++ help="show program's version number and exit"):
+++ super(_VersionAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ default=default,
+++ nargs=0,
+++ help=help)
+++ self.version = version
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ version = self.version
+++ if version is None:
+++ version = parser.version
+++ formatter = parser._get_formatter()
+++ formatter.add_text(version)
+++ parser.exit(message=formatter.format_help())
+++
+++
+++class _SubParsersAction(Action):
+++
+++ class _ChoicesPseudoAction(Action):
+++
+++ def __init__(self, name, help):
+++ sup = super(_SubParsersAction._ChoicesPseudoAction, self)
+++ sup.__init__(option_strings=[], dest=name, help=help)
+++
+++ def __init__(self,
+++ option_strings,
+++ prog,
+++ parser_class,
+++ dest=SUPPRESS,
+++ help=None,
+++ metavar=None):
+++
+++ self._prog_prefix = prog
+++ self._parser_class = parser_class
+++ self._name_parser_map = {}
+++ self._choices_actions = []
+++
+++ super(_SubParsersAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=PARSER,
+++ choices=self._name_parser_map,
+++ help=help,
+++ metavar=metavar)
+++
+++ def add_parser(self, name, **kwargs):
+++ # set prog from the existing prefix
+++ if kwargs.get('prog') is None:
+++ kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
+++
+++ # create a pseudo-action to hold the choice help
+++ if 'help' in kwargs:
+++ help = kwargs.pop('help')
+++ choice_action = self._ChoicesPseudoAction(name, help)
+++ self._choices_actions.append(choice_action)
+++
+++ # create the parser and add it to the map
+++ parser = self._parser_class(**kwargs)
+++ self._name_parser_map[name] = parser
+++ return parser
+++
+++ def _get_subactions(self):
+++ return self._choices_actions
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ parser_name = values[0]
+++ arg_strings = values[1:]
+++
+++ # set the parser name if requested
+++ if self.dest is not SUPPRESS:
+++ setattr(namespace, self.dest, parser_name)
+++
+++ # select the parser
+++ try:
+++ parser = self._name_parser_map[parser_name]
+++ except KeyError:
+++ tup = parser_name, ', '.join(self._name_parser_map)
+++ msg = _('unknown parser %r (choices: %s)' % tup)
+++ raise ArgumentError(self, msg)
+++
+++ # parse all the remaining options into the namespace
+++ # store any unrecognized options on the object, so that the top
+++ # level parser can decide what to do with them
+++ namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
+++ if arg_strings:
+++ vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
+++ getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
+++
+++
+++# ==============
+++# Type classes
+++# ==============
+++
+++class FileType(object):
+++ """Factory for creating file object types
+++
+++ Instances of FileType are typically passed as type= arguments to the
+++ ArgumentParser add_argument() method.
+++
+++ Keyword Arguments:
+++ - mode -- A string indicating how the file is to be opened. Accepts the
+++ same values as the builtin open() function.
+++ - bufsize -- The file's desired buffer size. Accepts the same values as
+++ the builtin open() function.
+++ """
+++
+++ def __init__(self, mode='r', bufsize=None):
+++ self._mode = mode
+++ self._bufsize = bufsize
+++
+++ def __call__(self, string):
+++ # the special argument "-" means sys.std{in,out}
+++ if string == '-':
+++ if 'r' in self._mode:
+++ return _sys.stdin
+++ elif 'w' in self._mode:
+++ return _sys.stdout
+++ else:
+++ msg = _('argument "-" with mode %r' % self._mode)
+++ raise ValueError(msg)
+++
+++ # all other arguments are used as file names
+++ if self._bufsize:
+++ return open(string, self._mode, self._bufsize)
+++ else:
+++ return open(string, self._mode)
+++
+++ def __repr__(self):
+++ args = [self._mode, self._bufsize]
+++ args_str = ', '.join([repr(arg) for arg in args if arg is not None])
+++ return '%s(%s)' % (type(self).__name__, args_str)
+++
+++# ===========================
+++# Optional and Positional Parsing
+++# ===========================
+++
+++class Namespace(_AttributeHolder):
+++ """Simple object for storing attributes.
+++
+++ Implements equality by attribute names and values, and provides a simple
+++ string representation.
+++ """
+++
+++ def __init__(self, **kwargs):
+++ for name in kwargs:
+++ setattr(self, name, kwargs[name])
+++
+++ __hash__ = None
+++
+++ def __eq__(self, other):
+++ return vars(self) == vars(other)
+++
+++ def __ne__(self, other):
+++ return not (self == other)
+++
+++ def __contains__(self, key):
+++ return key in self.__dict__
+++
+++
+++class _ActionsContainer(object):
+++
+++ def __init__(self,
+++ description,
+++ prefix_chars,
+++ argument_default,
+++ conflict_handler):
+++ super(_ActionsContainer, self).__init__()
+++
+++ self.description = description
+++ self.argument_default = argument_default
+++ self.prefix_chars = prefix_chars
+++ self.conflict_handler = conflict_handler
+++
+++ # set up registries
+++ self._registries = {}
+++
+++ # register actions
+++ self.register('action', None, _StoreAction)
+++ self.register('action', 'store', _StoreAction)
+++ self.register('action', 'store_const', _StoreConstAction)
+++ self.register('action', 'store_true', _StoreTrueAction)
+++ self.register('action', 'store_false', _StoreFalseAction)
+++ self.register('action', 'append', _AppendAction)
+++ self.register('action', 'append_const', _AppendConstAction)
+++ self.register('action', 'count', _CountAction)
+++ self.register('action', 'help', _HelpAction)
+++ self.register('action', 'version', _VersionAction)
+++ self.register('action', 'parsers', _SubParsersAction)
+++
+++ # raise an exception if the conflict handler is invalid
+++ self._get_handler()
+++
+++ # action storage
+++ self._actions = []
+++ self._option_string_actions = {}
+++
+++ # groups
+++ self._action_groups = []
+++ self._mutually_exclusive_groups = []
+++
+++ # defaults storage
+++ self._defaults = {}
+++
+++ # determines whether an "option" looks like a negative number
+++ self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
+++
+++ # whether or not there are any optionals that look like negative
+++ # numbers -- uses a list so it can be shared and edited
+++ self._has_negative_number_optionals = []
+++
+++ # ====================
+++ # Registration methods
+++ # ====================
+++ def register(self, registry_name, value, object):
+++ registry = self._registries.setdefault(registry_name, {})
+++ registry[value] = object
+++
+++ def _registry_get(self, registry_name, value, default=None):
+++ return self._registries[registry_name].get(value, default)
+++
+++ # ==================================
+++ # Namespace default accessor methods
+++ # ==================================
+++ def set_defaults(self, **kwargs):
+++ self._defaults.update(kwargs)
+++
+++ # if these defaults match any existing arguments, replace
+++ # the previous default on the object with the new one
+++ for action in self._actions:
+++ if action.dest in kwargs:
+++ action.default = kwargs[action.dest]
+++
+++ def get_default(self, dest):
+++ for action in self._actions:
+++ if action.dest == dest and action.default is not None:
+++ return action.default
+++ return self._defaults.get(dest, None)
+++
+++
+++ # =======================
+++ # Adding argument actions
+++ # =======================
+++ def add_argument(self, *args, **kwargs):
+++ """
+++ add_argument(dest, ..., name=value, ...)
+++ add_argument(option_string, option_string, ..., name=value, ...)
+++ """
+++
+++ # if no positional args are supplied or only one is supplied and
+++ # it doesn't look like an option string, parse a positional
+++ # argument
+++ chars = self.prefix_chars
+++ if not args or len(args) == 1 and args[0][0] not in chars:
+++ if args and 'dest' in kwargs:
+++ raise ValueError('dest supplied twice for positional argument')
+++ kwargs = self._get_positional_kwargs(*args, **kwargs)
+++
+++ # otherwise, we're adding an optional argument
+++ else:
+++ kwargs = self._get_optional_kwargs(*args, **kwargs)
+++
+++ # if no default was supplied, use the parser-level default
+++ if 'default' not in kwargs:
+++ dest = kwargs['dest']
+++ if dest in self._defaults:
+++ kwargs['default'] = self._defaults[dest]
+++ elif self.argument_default is not None:
+++ kwargs['default'] = self.argument_default
+++
+++ # create the action object, and add it to the parser
+++ action_class = self._pop_action_class(kwargs)
+++ if not _callable(action_class):
+++ raise ValueError('unknown action "%s"' % action_class)
+++ action = action_class(**kwargs)
+++
+++ # raise an error if the action type is not callable
+++ type_func = self._registry_get('type', action.type, action.type)
+++ if not _callable(type_func):
+++ raise ValueError('%r is not callable' % type_func)
+++
+++ return self._add_action(action)
+++
+++ def add_argument_group(self, *args, **kwargs):
+++ group = _ArgumentGroup(self, *args, **kwargs)
+++ self._action_groups.append(group)
+++ return group
+++
+++ def add_mutually_exclusive_group(self, **kwargs):
+++ group = _MutuallyExclusiveGroup(self, **kwargs)
+++ self._mutually_exclusive_groups.append(group)
+++ return group
+++
+++ def _add_action(self, action):
+++ # resolve any conflicts
+++ self._check_conflict(action)
+++
+++ # add to actions list
+++ self._actions.append(action)
+++ action.container = self
+++
+++ # index the action by any option strings it has
+++ for option_string in action.option_strings:
+++ self._option_string_actions[option_string] = action
+++
+++ # set the flag if any option strings look like negative numbers
+++ for option_string in action.option_strings:
+++ if self._negative_number_matcher.match(option_string):
+++ if not self._has_negative_number_optionals:
+++ self._has_negative_number_optionals.append(True)
+++
+++ # return the created action
+++ return action
+++
+++ def _remove_action(self, action):
+++ self._actions.remove(action)
+++
+++ def _add_container_actions(self, container):
+++ # collect groups by titles
+++ title_group_map = {}
+++ for group in self._action_groups:
+++ if group.title in title_group_map:
+++ msg = _('cannot merge actions - two groups are named %r')
+++ raise ValueError(msg % (group.title))
+++ title_group_map[group.title] = group
+++
+++ # map each action to its group
+++ group_map = {}
+++ for group in container._action_groups:
+++
+++ # if a group with the title exists, use that, otherwise
+++ # create a new group matching the container's group
+++ if group.title not in title_group_map:
+++ title_group_map[group.title] = self.add_argument_group(
+++ title=group.title,
+++ description=group.description,
+++ conflict_handler=group.conflict_handler)
+++
+++ # map the actions to their new group
+++ for action in group._group_actions:
+++ group_map[action] = title_group_map[group.title]
+++
+++ # add container's mutually exclusive groups
+++ # NOTE: if add_mutually_exclusive_group ever gains title= and
+++ # description= then this code will need to be expanded as above
+++ for group in container._mutually_exclusive_groups:
+++ mutex_group = self.add_mutually_exclusive_group(
+++ required=group.required)
+++
+++ # map the actions to their new mutex group
+++ for action in group._group_actions:
+++ group_map[action] = mutex_group
+++
+++ # add all actions to this container or their group
+++ for action in container._actions:
+++ group_map.get(action, self)._add_action(action)
+++
+++ def _get_positional_kwargs(self, dest, **kwargs):
+++ # make sure required is not specified
+++ if 'required' in kwargs:
+++ msg = _("'required' is an invalid argument for positionals")
+++ raise TypeError(msg)
+++
+++ # mark positional arguments as required if at least one is
+++ # always required
+++ if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
+++ kwargs['required'] = True
+++ if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
+++ kwargs['required'] = True
+++
+++ # return the keyword arguments with no option strings
+++ return dict(kwargs, dest=dest, option_strings=[])
+++
+++ def _get_optional_kwargs(self, *args, **kwargs):
+++ # determine short and long option strings
+++ option_strings = []
+++ long_option_strings = []
+++ for option_string in args:
+++ # error on strings that don't start with an appropriate prefix
+++ if not option_string[0] in self.prefix_chars:
+++ msg = _('invalid option string %r: '
+++ 'must start with a character %r')
+++ tup = option_string, self.prefix_chars
+++ raise ValueError(msg % tup)
+++
+++ # strings starting with two prefix characters are long options
+++ option_strings.append(option_string)
+++ if option_string[0] in self.prefix_chars:
+++ if len(option_string) > 1:
+++ if option_string[1] in self.prefix_chars:
+++ long_option_strings.append(option_string)
+++
+++ # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
+++ dest = kwargs.pop('dest', None)
+++ if dest is None:
+++ if long_option_strings:
+++ dest_option_string = long_option_strings[0]
+++ else:
+++ dest_option_string = option_strings[0]
+++ dest = dest_option_string.lstrip(self.prefix_chars)
+++ if not dest:
+++ msg = _('dest= is required for options like %r')
+++ raise ValueError(msg % option_string)
+++ dest = dest.replace('-', '_')
+++
+++ # return the updated keyword arguments
+++ return dict(kwargs, dest=dest, option_strings=option_strings)
+++
+++ def _pop_action_class(self, kwargs, default=None):
+++ action = kwargs.pop('action', default)
+++ return self._registry_get('action', action, action)
+++
+++ def _get_handler(self):
+++ # determine function from conflict handler string
+++ handler_func_name = '_handle_conflict_%s' % self.conflict_handler
+++ try:
+++ return getattr(self, handler_func_name)
+++ except AttributeError:
+++ msg = _('invalid conflict_resolution value: %r')
+++ raise ValueError(msg % self.conflict_handler)
+++
+++ def _check_conflict(self, action):
+++
+++ # find all options that conflict with this option
+++ confl_optionals = []
+++ for option_string in action.option_strings:
+++ if option_string in self._option_string_actions:
+++ confl_optional = self._option_string_actions[option_string]
+++ confl_optionals.append((option_string, confl_optional))
+++
+++ # resolve any conflicts
+++ if confl_optionals:
+++ conflict_handler = self._get_handler()
+++ conflict_handler(action, confl_optionals)
+++
+++ def _handle_conflict_error(self, action, conflicting_actions):
+++ message = _('conflicting option string(s): %s')
+++ conflict_string = ', '.join([option_string
+++ for option_string, action
+++ in conflicting_actions])
+++ raise ArgumentError(action, message % conflict_string)
+++
+++ def _handle_conflict_resolve(self, action, conflicting_actions):
+++
+++ # remove all conflicting options
+++ for option_string, action in conflicting_actions:
+++
+++ # remove the conflicting option
+++ action.option_strings.remove(option_string)
+++ self._option_string_actions.pop(option_string, None)
+++
+++ # if the option now has no option string, remove it from the
+++ # container holding it
+++ if not action.option_strings:
+++ action.container._remove_action(action)
+++
+++
+++class _ArgumentGroup(_ActionsContainer):
+++
+++ def __init__(self, container, title=None, description=None, **kwargs):
+++ # add any missing keyword arguments by checking the container
+++ update = kwargs.setdefault
+++ update('conflict_handler', container.conflict_handler)
+++ update('prefix_chars', container.prefix_chars)
+++ update('argument_default', container.argument_default)
+++ super_init = super(_ArgumentGroup, self).__init__
+++ super_init(description=description, **kwargs)
+++
+++ # group attributes
+++ self.title = title
+++ self._group_actions = []
+++
+++ # share most attributes with the container
+++ self._registries = container._registries
+++ self._actions = container._actions
+++ self._option_string_actions = container._option_string_actions
+++ self._defaults = container._defaults
+++ self._has_negative_number_optionals = \
+++ container._has_negative_number_optionals
+++
+++ def _add_action(self, action):
+++ action = super(_ArgumentGroup, self)._add_action(action)
+++ self._group_actions.append(action)
+++ return action
+++
+++ def _remove_action(self, action):
+++ super(_ArgumentGroup, self)._remove_action(action)
+++ self._group_actions.remove(action)
+++
+++
+++class _MutuallyExclusiveGroup(_ArgumentGroup):
+++
+++ def __init__(self, container, required=False):
+++ super(_MutuallyExclusiveGroup, self).__init__(container)
+++ self.required = required
+++ self._container = container
+++
+++ def _add_action(self, action):
+++ if action.required:
+++ msg = _('mutually exclusive arguments must be optional')
+++ raise ValueError(msg)
+++ action = self._container._add_action(action)
+++ self._group_actions.append(action)
+++ return action
+++
+++ def _remove_action(self, action):
+++ self._container._remove_action(action)
+++ self._group_actions.remove(action)
+++
+++
+++class ArgumentParser(_AttributeHolder, _ActionsContainer):
+++ """Object for parsing command line strings into Python objects.
+++
+++ Keyword Arguments:
+++ - prog -- The name of the program (default: sys.argv[0])
+++ - usage -- A usage message (default: auto-generated from arguments)
+++ - description -- A description of what the program does
+++ - epilog -- Text following the argument descriptions
+++ - parents -- Parsers whose arguments should be copied into this one
+++ - formatter_class -- HelpFormatter class for printing help messages
+++ - prefix_chars -- Characters that prefix optional arguments
+++ - fromfile_prefix_chars -- Characters that prefix files containing
+++ additional arguments
+++ - argument_default -- The default value for all arguments
+++ - conflict_handler -- String indicating how to handle conflicts
+++ - add_help -- Add a -h/-help option
+++ """
+++
+++ def __init__(self,
+++ prog=None,
+++ usage=None,
+++ description=None,
+++ epilog=None,
+++ version=None,
+++ parents=[],
+++ formatter_class=HelpFormatter,
+++ prefix_chars='-',
+++ fromfile_prefix_chars=None,
+++ argument_default=None,
+++ conflict_handler='error',
+++ add_help=True):
+++
+++ if version is not None:
+++ import warnings
+++ warnings.warn(
+++ """The "version" argument to ArgumentParser is deprecated. """
+++ """Please use """
+++ """"add_argument(..., action='version', version="N", ...)" """
+++ """instead""", DeprecationWarning)
+++
+++ superinit = super(ArgumentParser, self).__init__
+++ superinit(description=description,
+++ prefix_chars=prefix_chars,
+++ argument_default=argument_default,
+++ conflict_handler=conflict_handler)
+++
+++ # default setting for prog
+++ if prog is None:
+++ prog = _os.path.basename(_sys.argv[0])
+++
+++ self.prog = prog
+++ self.usage = usage
+++ self.epilog = epilog
+++ self.version = version
+++ self.formatter_class = formatter_class
+++ self.fromfile_prefix_chars = fromfile_prefix_chars
+++ self.add_help = add_help
+++
+++ add_group = self.add_argument_group
+++ self._positionals = add_group(_('positional arguments'))
+++ self._optionals = add_group(_('optional arguments'))
+++ self._subparsers = None
+++
+++ # register types
+++ def identity(string):
+++ return string
+++ self.register('type', None, identity)
+++
+++ # add help and version arguments if necessary
+++ # (using explicit default to override global argument_default)
+++ if '-' in prefix_chars:
+++ default_prefix = '-'
+++ else:
+++ default_prefix = prefix_chars[0]
+++ if self.add_help:
+++ self.add_argument(
+++ default_prefix+'h', default_prefix*2+'help',
+++ action='help', default=SUPPRESS,
+++ help=_('show this help message and exit'))
+++ if self.version:
+++ self.add_argument(
+++ default_prefix+'v', default_prefix*2+'version',
+++ action='version', default=SUPPRESS,
+++ version=self.version,
+++ help=_("show program's version number and exit"))
+++
+++ # add parent arguments and defaults
+++ for parent in parents:
+++ self._add_container_actions(parent)
+++ try:
+++ defaults = parent._defaults
+++ except AttributeError:
+++ pass
+++ else:
+++ self._defaults.update(defaults)
+++
+++ # =======================
+++ # Pretty __repr__ methods
+++ # =======================
+++ def _get_kwargs(self):
+++ names = [
+++ 'prog',
+++ 'usage',
+++ 'description',
+++ 'version',
+++ 'formatter_class',
+++ 'conflict_handler',
+++ 'add_help',
+++ ]
+++ return [(name, getattr(self, name)) for name in names]
+++
+++ # ==================================
+++ # Optional/Positional adding methods
+++ # ==================================
+++ def add_subparsers(self, **kwargs):
+++ if self._subparsers is not None:
+++ self.error(_('cannot have multiple subparser arguments'))
+++
+++ # add the parser class to the arguments if it's not present
+++ kwargs.setdefault('parser_class', type(self))
+++
+++ if 'title' in kwargs or 'description' in kwargs:
+++ title = _(kwargs.pop('title', 'subcommands'))
+++ description = _(kwargs.pop('description', None))
+++ self._subparsers = self.add_argument_group(title, description)
+++ else:
+++ self._subparsers = self._positionals
+++
+++ # prog defaults to the usage message of this parser, skipping
+++ # optional arguments and with no "usage:" prefix
+++ if kwargs.get('prog') is None:
+++ formatter = self._get_formatter()
+++ positionals = self._get_positional_actions()
+++ groups = self._mutually_exclusive_groups
+++ formatter.add_usage(self.usage, positionals, groups, '')
+++ kwargs['prog'] = formatter.format_help().strip()
+++
+++ # create the parsers action and add it to the positionals list
+++ parsers_class = self._pop_action_class(kwargs, 'parsers')
+++ action = parsers_class(option_strings=[], **kwargs)
+++ self._subparsers._add_action(action)
+++
+++ # return the created parsers action
+++ return action
+++
+++ def _add_action(self, action):
+++ if action.option_strings:
+++ self._optionals._add_action(action)
+++ else:
+++ self._positionals._add_action(action)
+++ return action
+++
+++ def _get_optional_actions(self):
+++ return [action
+++ for action in self._actions
+++ if action.option_strings]
+++
+++ def _get_positional_actions(self):
+++ return [action
+++ for action in self._actions
+++ if not action.option_strings]
+++
+++ # =====================================
+++ # Command line argument parsing methods
+++ # =====================================
+++ def parse_args(self, args=None, namespace=None):
+++ args, argv = self.parse_known_args(args, namespace)
+++ if argv:
+++ msg = _('unrecognized arguments: %s')
+++ self.error(msg % ' '.join(argv))
+++ return args
+++
+++ def parse_known_args(self, args=None, namespace=None):
+++ # args default to the system args
+++ if args is None:
+++ args = _sys.argv[1:]
+++
+++ # default Namespace built from parser defaults
+++ if namespace is None:
+++ namespace = Namespace()
+++
+++ # add any action defaults that aren't present
+++ for action in self._actions:
+++ if action.dest is not SUPPRESS:
+++ if not hasattr(namespace, action.dest):
+++ if action.default is not SUPPRESS:
+++ default = action.default
+++ if isinstance(action.default, basestring):
+++ default = self._get_value(action, default)
+++ setattr(namespace, action.dest, default)
+++
+++ # add any parser defaults that aren't present
+++ for dest in self._defaults:
+++ if not hasattr(namespace, dest):
+++ setattr(namespace, dest, self._defaults[dest])
+++
+++ # parse the arguments and exit if there are any errors
+++ try:
+++ namespace, args = self._parse_known_args(args, namespace)
+++ if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
+++ args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
+++ delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
+++ return namespace, args
+++ except ArgumentError:
+++ err = _sys.exc_info()[1]
+++ self.error(str(err))
+++
+++ def _parse_known_args(self, arg_strings, namespace):
+++ # replace arg strings that are file references
+++ if self.fromfile_prefix_chars is not None:
+++ arg_strings = self._read_args_from_files(arg_strings)
+++
+++ # map all mutually exclusive arguments to the other arguments
+++ # they can't occur with
+++ action_conflicts = {}
+++ for mutex_group in self._mutually_exclusive_groups:
+++ group_actions = mutex_group._group_actions
+++ for i, mutex_action in enumerate(mutex_group._group_actions):
+++ conflicts = action_conflicts.setdefault(mutex_action, [])
+++ conflicts.extend(group_actions[:i])
+++ conflicts.extend(group_actions[i + 1:])
+++
+++ # find all option indices, and determine the arg_string_pattern
+++ # which has an 'O' if there is an option at an index,
+++ # an 'A' if there is an argument, or a '-' if there is a '--'
+++ option_string_indices = {}
+++ arg_string_pattern_parts = []
+++ arg_strings_iter = iter(arg_strings)
+++ for i, arg_string in enumerate(arg_strings_iter):
+++
+++ # all args after -- are non-options
+++ if arg_string == '--':
+++ arg_string_pattern_parts.append('-')
+++ for arg_string in arg_strings_iter:
+++ arg_string_pattern_parts.append('A')
+++
+++ # otherwise, add the arg to the arg strings
+++ # and note the index if it was an option
+++ else:
+++ option_tuple = self._parse_optional(arg_string)
+++ if option_tuple is None:
+++ pattern = 'A'
+++ else:
+++ option_string_indices[i] = option_tuple
+++ pattern = 'O'
+++ arg_string_pattern_parts.append(pattern)
+++
+++ # join the pieces together to form the pattern
+++ arg_strings_pattern = ''.join(arg_string_pattern_parts)
+++
+++ # converts arg strings to the appropriate and then takes the action
+++ seen_actions = set()
+++ seen_non_default_actions = set()
+++
+++ def take_action(action, argument_strings, option_string=None):
+++ seen_actions.add(action)
+++ argument_values = self._get_values(action, argument_strings)
+++
+++ # error if this argument is not allowed with other previously
+++ # seen arguments, assuming that actions that use the default
+++ # value don't really count as "present"
+++ if argument_values is not action.default:
+++ seen_non_default_actions.add(action)
+++ for conflict_action in action_conflicts.get(action, []):
+++ if conflict_action in seen_non_default_actions:
+++ msg = _('not allowed with argument %s')
+++ action_name = _get_action_name(conflict_action)
+++ raise ArgumentError(action, msg % action_name)
+++
+++ # take the action if we didn't receive a SUPPRESS value
+++ # (e.g. from a default)
+++ if argument_values is not SUPPRESS:
+++ action(self, namespace, argument_values, option_string)
+++
+++ # function to convert arg_strings into an optional action
+++ def consume_optional(start_index):
+++
+++ # get the optional identified at this index
+++ option_tuple = option_string_indices[start_index]
+++ action, option_string, explicit_arg = option_tuple
+++
+++ # identify additional optionals in the same arg string
+++ # (e.g. -xyz is the same as -x -y -z if no args are required)
+++ match_argument = self._match_argument
+++ action_tuples = []
+++ while True:
+++
+++ # if we found no optional action, skip it
+++ if action is None:
+++ extras.append(arg_strings[start_index])
+++ return start_index + 1
+++
+++ # if there is an explicit argument, try to match the
+++ # optional's string arguments to only this
+++ if explicit_arg is not None:
+++ arg_count = match_argument(action, 'A')
+++
+++ # if the action is a single-dash option and takes no
+++ # arguments, try to parse more single-dash options out
+++ # of the tail of the option string
+++ chars = self.prefix_chars
+++ if arg_count == 0 and option_string[1] not in chars:
+++ action_tuples.append((action, [], option_string))
+++ char = option_string[0]
+++ option_string = char + explicit_arg[0]
+++ new_explicit_arg = explicit_arg[1:] or None
+++ optionals_map = self._option_string_actions
+++ if option_string in optionals_map:
+++ action = optionals_map[option_string]
+++ explicit_arg = new_explicit_arg
+++ else:
+++ msg = _('ignored explicit argument %r')
+++ raise ArgumentError(action, msg % explicit_arg)
+++
+++ # if the action expect exactly one argument, we've
+++ # successfully matched the option; exit the loop
+++ elif arg_count == 1:
+++ stop = start_index + 1
+++ args = [explicit_arg]
+++ action_tuples.append((action, args, option_string))
+++ break
+++
+++ # error if a double-dash option did not use the
+++ # explicit argument
+++ else:
+++ msg = _('ignored explicit argument %r')
+++ raise ArgumentError(action, msg % explicit_arg)
+++
+++ # if there is no explicit argument, try to match the
+++ # optional's string arguments with the following strings
+++ # if successful, exit the loop
+++ else:
+++ start = start_index + 1
+++ selected_patterns = arg_strings_pattern[start:]
+++ arg_count = match_argument(action, selected_patterns)
+++ stop = start + arg_count
+++ args = arg_strings[start:stop]
+++ action_tuples.append((action, args, option_string))
+++ break
+++
+++ # add the Optional to the list and return the index at which
+++ # the Optional's string args stopped
+++ assert action_tuples
+++ for action, args, option_string in action_tuples:
+++ take_action(action, args, option_string)
+++ return stop
+++
+++ # the list of Positionals left to be parsed; this is modified
+++ # by consume_positionals()
+++ positionals = self._get_positional_actions()
+++
+++ # function to convert arg_strings into positional actions
+++ def consume_positionals(start_index):
+++ # match as many Positionals as possible
+++ match_partial = self._match_arguments_partial
+++ selected_pattern = arg_strings_pattern[start_index:]
+++ arg_counts = match_partial(positionals, selected_pattern)
+++
+++ # slice off the appropriate arg strings for each Positional
+++ # and add the Positional and its args to the list
+++ for action, arg_count in zip(positionals, arg_counts):
+++ args = arg_strings[start_index: start_index + arg_count]
+++ start_index += arg_count
+++ take_action(action, args)
+++
+++ # slice off the Positionals that we just parsed and return the
+++ # index at which the Positionals' string args stopped
+++ positionals[:] = positionals[len(arg_counts):]
+++ return start_index
+++
+++ # consume Positionals and Optionals alternately, until we have
+++ # passed the last option string
+++ extras = []
+++ start_index = 0
+++ if option_string_indices:
+++ max_option_string_index = max(option_string_indices)
+++ else:
+++ max_option_string_index = -1
+++ while start_index <= max_option_string_index:
+++
+++ # consume any Positionals preceding the next option
+++ next_option_string_index = min([
+++ index
+++ for index in option_string_indices
+++ if index >= start_index])
+++ if start_index != next_option_string_index:
+++ positionals_end_index = consume_positionals(start_index)
+++
+++ # only try to parse the next optional if we didn't consume
+++ # the option string during the positionals parsing
+++ if positionals_end_index > start_index:
+++ start_index = positionals_end_index
+++ continue
+++ else:
+++ start_index = positionals_end_index
+++
+++ # if we consumed all the positionals we could and we're not
+++ # at the index of an option string, there were extra arguments
+++ if start_index not in option_string_indices:
+++ strings = arg_strings[start_index:next_option_string_index]
+++ extras.extend(strings)
+++ start_index = next_option_string_index
+++
+++ # consume the next optional and any arguments for it
+++ start_index = consume_optional(start_index)
+++
+++ # consume any positionals following the last Optional
+++ stop_index = consume_positionals(start_index)
+++
+++ # if we didn't consume all the argument strings, there were extras
+++ extras.extend(arg_strings[stop_index:])
+++
+++ # if we didn't use all the Positional objects, there were too few
+++ # arg strings supplied.
+++ if positionals:
+++ self.error(_('too few arguments'))
+++
+++ # make sure all required actions were present
+++ for action in self._actions:
+++ if action.required:
+++ if action not in seen_actions:
+++ name = _get_action_name(action)
+++ self.error(_('argument %s is required') % name)
+++
+++ # make sure all required groups had one option present
+++ for group in self._mutually_exclusive_groups:
+++ if group.required:
+++ for action in group._group_actions:
+++ if action in seen_non_default_actions:
+++ break
+++
+++ # if no actions were used, report the error
+++ else:
+++ names = [_get_action_name(action)
+++ for action in group._group_actions
+++ if action.help is not SUPPRESS]
+++ msg = _('one of the arguments %s is required')
+++ self.error(msg % ' '.join(names))
+++
+++ # return the updated namespace and the extra arguments
+++ return namespace, extras
+++
+++ def _read_args_from_files(self, arg_strings):
+++ # expand arguments referencing files
+++ new_arg_strings = []
+++ for arg_string in arg_strings:
+++
+++ # for regular arguments, just add them back into the list
+++ if arg_string[0] not in self.fromfile_prefix_chars:
+++ new_arg_strings.append(arg_string)
+++
+++ # replace arguments referencing files with the file content
+++ else:
+++ try:
+++ args_file = open(arg_string[1:])
+++ try:
+++ arg_strings = []
+++ for arg_line in args_file.read().splitlines():
+++ for arg in self.convert_arg_line_to_args(arg_line):
+++ arg_strings.append(arg)
+++ arg_strings = self._read_args_from_files(arg_strings)
+++ new_arg_strings.extend(arg_strings)
+++ finally:
+++ args_file.close()
+++ except IOError:
+++ err = _sys.exc_info()[1]
+++ self.error(str(err))
+++
+++ # return the modified argument list
+++ return new_arg_strings
+++
+++ def convert_arg_line_to_args(self, arg_line):
+++ return [arg_line]
+++
+++ def _match_argument(self, action, arg_strings_pattern):
+++ # match the pattern for this action to the arg strings
+++ nargs_pattern = self._get_nargs_pattern(action)
+++ match = _re.match(nargs_pattern, arg_strings_pattern)
+++
+++ # raise an exception if we weren't able to find a match
+++ if match is None:
+++ nargs_errors = {
+++ None: _('expected one argument'),
+++ OPTIONAL: _('expected at most one argument'),
+++ ONE_OR_MORE: _('expected at least one argument'),
+++ }
+++ default = _('expected %s argument(s)') % action.nargs
+++ msg = nargs_errors.get(action.nargs, default)
+++ raise ArgumentError(action, msg)
+++
+++ # return the number of arguments matched
+++ return len(match.group(1))
+++
+++ def _match_arguments_partial(self, actions, arg_strings_pattern):
+++ # progressively shorten the actions list by slicing off the
+++ # final actions until we find a match
+++ result = []
+++ for i in range(len(actions), 0, -1):
+++ actions_slice = actions[:i]
+++ pattern = ''.join([self._get_nargs_pattern(action)
+++ for action in actions_slice])
+++ match = _re.match(pattern, arg_strings_pattern)
+++ if match is not None:
+++ result.extend([len(string) for string in match.groups()])
+++ break
+++
+++ # return the list of arg string counts
+++ return result
+++
+++ def _parse_optional(self, arg_string):
+++ # if it's an empty string, it was meant to be a positional
+++ if not arg_string:
+++ return None
+++
+++ # if it doesn't start with a prefix, it was meant to be positional
+++ if not arg_string[0] in self.prefix_chars:
+++ return None
+++
+++ # if the option string is present in the parser, return the action
+++ if arg_string in self._option_string_actions:
+++ action = self._option_string_actions[arg_string]
+++ return action, arg_string, None
+++
+++ # if it's just a single character, it was meant to be positional
+++ if len(arg_string) == 1:
+++ return None
+++
+++ # if the option string before the "=" is present, return the action
+++ if '=' in arg_string:
+++ option_string, explicit_arg = arg_string.split('=', 1)
+++ if option_string in self._option_string_actions:
+++ action = self._option_string_actions[option_string]
+++ return action, option_string, explicit_arg
+++
+++ # search through all possible prefixes of the option string
+++ # and all actions in the parser for possible interpretations
+++ option_tuples = self._get_option_tuples(arg_string)
+++
+++ # if multiple actions match, the option string was ambiguous
+++ if len(option_tuples) > 1:
+++ options = ', '.join([option_string
+++ for action, option_string, explicit_arg in option_tuples])
+++ tup = arg_string, options
+++ self.error(_('ambiguous option: %s could match %s') % tup)
+++
+++ # if exactly one action matched, this segmentation is good,
+++ # so return the parsed action
+++ elif len(option_tuples) == 1:
+++ option_tuple, = option_tuples
+++ return option_tuple
+++
+++ # if it was not found as an option, but it looks like a negative
+++ # number, it was meant to be positional
+++ # unless there are negative-number-like options
+++ if self._negative_number_matcher.match(arg_string):
+++ if not self._has_negative_number_optionals:
+++ return None
+++
+++ # if it contains a space, it was meant to be a positional
+++ if ' ' in arg_string:
+++ return None
+++
+++ # it was meant to be an optional but there is no such option
+++ # in this parser (though it might be a valid option in a subparser)
+++ return None, arg_string, None
+++
+++ def _get_option_tuples(self, option_string):
+++ result = []
+++
+++ # option strings starting with two prefix characters are only
+++ # split at the '='
+++ chars = self.prefix_chars
+++ if option_string[0] in chars and option_string[1] in chars:
+++ if '=' in option_string:
+++ option_prefix, explicit_arg = option_string.split('=', 1)
+++ else:
+++ option_prefix = option_string
+++ explicit_arg = None
+++ for option_string in self._option_string_actions:
+++ if option_string.startswith(option_prefix):
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, explicit_arg
+++ result.append(tup)
+++
+++ # single character options can be concatenated with their arguments
+++ # but multiple character options always have to have their argument
+++ # separate
+++ elif option_string[0] in chars and option_string[1] not in chars:
+++ option_prefix = option_string
+++ explicit_arg = None
+++ short_option_prefix = option_string[:2]
+++ short_explicit_arg = option_string[2:]
+++
+++ for option_string in self._option_string_actions:
+++ if option_string == short_option_prefix:
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, short_explicit_arg
+++ result.append(tup)
+++ elif option_string.startswith(option_prefix):
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, explicit_arg
+++ result.append(tup)
+++
+++ # shouldn't ever get here
+++ else:
+++ self.error(_('unexpected option string: %s') % option_string)
+++
+++ # return the collected option tuples
+++ return result
+++
+++ def _get_nargs_pattern(self, action):
+++ # in all examples below, we have to allow for '--' args
+++ # which are represented as '-' in the pattern
+++ nargs = action.nargs
+++
+++ # the default (None) is assumed to be a single argument
+++ if nargs is None:
+++ nargs_pattern = '(-*A-*)'
+++
+++ # allow zero or one arguments
+++ elif nargs == OPTIONAL:
+++ nargs_pattern = '(-*A?-*)'
+++
+++ # allow zero or more arguments
+++ elif nargs == ZERO_OR_MORE:
+++ nargs_pattern = '(-*[A-]*)'
+++
+++ # allow one or more arguments
+++ elif nargs == ONE_OR_MORE:
+++ nargs_pattern = '(-*A[A-]*)'
+++
+++ # allow any number of options or arguments
+++ elif nargs == REMAINDER:
+++ nargs_pattern = '([-AO]*)'
+++
+++ # allow one argument followed by any number of options or arguments
+++ elif nargs == PARSER:
+++ nargs_pattern = '(-*A[-AO]*)'
+++
+++ # all others should be integers
+++ else:
+++ nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
+++
+++ # if this is an optional action, -- is not allowed
+++ if action.option_strings:
+++ nargs_pattern = nargs_pattern.replace('-*', '')
+++ nargs_pattern = nargs_pattern.replace('-', '')
+++
+++ # return the pattern
+++ return nargs_pattern
+++
+++ # ========================
+++ # Value conversion methods
+++ # ========================
+++ def _get_values(self, action, arg_strings):
+++ # for everything but PARSER args, strip out '--'
+++ if action.nargs not in [PARSER, REMAINDER]:
+++ arg_strings = [s for s in arg_strings if s != '--']
+++
+++ # optional argument produces a default when not present
+++ if not arg_strings and action.nargs == OPTIONAL:
+++ if action.option_strings:
+++ value = action.const
+++ else:
+++ value = action.default
+++ if isinstance(value, basestring):
+++ value = self._get_value(action, value)
+++ self._check_value(action, value)
+++
+++ # when nargs='*' on a positional, if there were no command-line
+++ # args, use the default if it is anything other than None
+++ elif (not arg_strings and action.nargs == ZERO_OR_MORE and
+++ not action.option_strings):
+++ if action.default is not None:
+++ value = action.default
+++ else:
+++ value = arg_strings
+++ self._check_value(action, value)
+++
+++ # single argument or optional argument produces a single value
+++ elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
+++ arg_string, = arg_strings
+++ value = self._get_value(action, arg_string)
+++ self._check_value(action, value)
+++
+++ # REMAINDER arguments convert all values, checking none
+++ elif action.nargs == REMAINDER:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++
+++ # PARSER arguments convert all values, but check only the first
+++ elif action.nargs == PARSER:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++ self._check_value(action, value[0])
+++
+++ # all other types of nargs produce a list
+++ else:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++ for v in value:
+++ self._check_value(action, v)
+++
+++ # return the converted value
+++ return value
+++
+++ def _get_value(self, action, arg_string):
+++ type_func = self._registry_get('type', action.type, action.type)
+++ if not _callable(type_func):
+++ msg = _('%r is not callable')
+++ raise ArgumentError(action, msg % type_func)
+++
+++ # convert the value to the appropriate type
+++ try:
+++ result = type_func(arg_string)
+++
+++ # ArgumentTypeErrors indicate errors
+++ except ArgumentTypeError:
+++ name = getattr(action.type, '__name__', repr(action.type))
+++ msg = str(_sys.exc_info()[1])
+++ raise ArgumentError(action, msg)
+++
+++ # TypeErrors or ValueErrors also indicate errors
+++ except (TypeError, ValueError):
+++ name = getattr(action.type, '__name__', repr(action.type))
+++ msg = _('invalid %s value: %r')
+++ raise ArgumentError(action, msg % (name, arg_string))
+++
+++ # return the converted value
+++ return result
+++
+++ def _check_value(self, action, value):
+++ # converted value must be one of the choices (if specified)
+++ if action.choices is not None and value not in action.choices:
+++ tup = value, ', '.join(map(repr, action.choices))
+++ msg = _('invalid choice: %r (choose from %s)') % tup
+++ raise ArgumentError(action, msg)
+++
+++ # =======================
+++ # Help-formatting methods
+++ # =======================
+++ def format_usage(self):
+++ formatter = self._get_formatter()
+++ formatter.add_usage(self.usage, self._actions,
+++ self._mutually_exclusive_groups)
+++ return formatter.format_help()
+++
+++ def format_help(self):
+++ formatter = self._get_formatter()
+++
+++ # usage
+++ formatter.add_usage(self.usage, self._actions,
+++ self._mutually_exclusive_groups)
+++
+++ # description
+++ formatter.add_text(self.description)
+++
+++ # positionals, optionals and user-defined groups
+++ for action_group in self._action_groups:
+++ formatter.start_section(action_group.title)
+++ formatter.add_text(action_group.description)
+++ formatter.add_arguments(action_group._group_actions)
+++ formatter.end_section()
+++
+++ # epilog
+++ formatter.add_text(self.epilog)
+++
+++ # determine help from format above
+++ return formatter.format_help()
+++
+++ def format_version(self):
+++ import warnings
+++ warnings.warn(
+++ 'The format_version method is deprecated -- the "version" '
+++ 'argument to ArgumentParser is no longer supported.',
+++ DeprecationWarning)
+++ formatter = self._get_formatter()
+++ formatter.add_text(self.version)
+++ return formatter.format_help()
+++
+++ def _get_formatter(self):
+++ return self.formatter_class(prog=self.prog)
+++
+++ # =====================
+++ # Help-printing methods
+++ # =====================
+++ def print_usage(self, file=None):
+++ if file is None:
+++ file = _sys.stdout
+++ self._print_message(self.format_usage(), file)
+++
+++ def print_help(self, file=None):
+++ if file is None:
+++ file = _sys.stdout
+++ self._print_message(self.format_help(), file)
+++
+++ def print_version(self, file=None):
+++ import warnings
+++ warnings.warn(
+++ 'The print_version method is deprecated -- the "version" '
+++ 'argument to ArgumentParser is no longer supported.',
+++ DeprecationWarning)
+++ self._print_message(self.format_version(), file)
+++
+++ def _print_message(self, message, file=None):
+++ if message:
+++ if file is None:
+++ file = _sys.stderr
+++ file.write(message)
+++
+++ # ===============
+++ # Exiting methods
+++ # ===============
+++ def exit(self, status=0, message=None):
+++ if message:
+++ self._print_message(message, _sys.stderr)
+++ _sys.exit(status)
+++
+++ def error(self, message):
+++ """error(message: string)
+++
+++ Prints a usage message incorporating the message to stderr and
+++ exits.
+++
+++ If you override this in a subclass, it should not return -- it
+++ should either exit or raise an exception.
+++ """
+++ self.print_usage(_sys.stderr)
+++ self.exit(2, _('%s: error: %s\n') % (self.prog, message))
+++# Author: Steven J. Bethard <steven.bethard at gmail.com>.
+++
+++"""Command-line parsing library
+++
+++This module is an optparse-inspired command-line parsing library that:
+++
+++ - handles both optional and positional arguments
+++ - produces highly informative usage messages
+++ - supports parsers that dispatch to sub-parsers
+++
+++The following is a simple usage example that sums integers from the
+++command-line and writes the result to a file::
+++
+++ parser = argparse.ArgumentParser(
+++ description='sum the integers at the command line')
+++ parser.add_argument(
+++ 'integers', metavar='int', nargs='+', type=int,
+++ help='an integer to be summed')
+++ parser.add_argument(
+++ '--log', default=sys.stdout, type=argparse.FileType('w'),
+++ help='the file where the sum should be written')
+++ args = parser.parse_args()
+++ args.log.write('%s' % sum(args.integers))
+++ args.log.close()
+++
+++The module contains the following public classes:
+++
+++ - ArgumentParser -- The main entry point for command-line parsing. As the
+++ example above shows, the add_argument() method is used to populate
+++ the parser with actions for optional and positional arguments. Then
+++ the parse_args() method is invoked to convert the args at the
+++ command-line into an object with attributes.
+++
+++ - ArgumentError -- The exception raised by ArgumentParser objects when
+++ there are errors with the parser's actions. Errors raised while
+++ parsing the command-line are caught by ArgumentParser and emitted
+++ as command-line messages.
+++
+++ - FileType -- A factory for defining types of files to be created. As the
+++ example above shows, instances of FileType are typically passed as
+++ the type= argument of add_argument() calls.
+++
+++ - Action -- The base class for parser actions. Typically actions are
+++ selected by passing strings like 'store_true' or 'append_const' to
+++ the action= argument of add_argument(). However, for greater
+++ customization of ArgumentParser actions, subclasses of Action may
+++ be defined and passed as the action= argument.
+++
+++ - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
+++ ArgumentDefaultsHelpFormatter -- Formatter classes which
+++ may be passed as the formatter_class= argument to the
+++ ArgumentParser constructor. HelpFormatter is the default,
+++ RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
+++ not to change the formatting for help text, and
+++ ArgumentDefaultsHelpFormatter adds information about argument defaults
+++ to the help.
+++
+++All other classes in this module are considered implementation details.
+++(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
+++considered public as object names -- the API of the formatter objects is
+++still considered an implementation detail.)
+++"""
+++
+++__version__ = '1.2.1'
+++__all__ = [
+++ 'ArgumentParser',
+++ 'ArgumentError',
+++ 'ArgumentTypeError',
+++ 'FileType',
+++ 'HelpFormatter',
+++ 'ArgumentDefaultsHelpFormatter',
+++ 'RawDescriptionHelpFormatter',
+++ 'RawTextHelpFormatter',
+++ 'Namespace',
+++ 'Action',
+++ 'ONE_OR_MORE',
+++ 'OPTIONAL',
+++ 'PARSER',
+++ 'REMAINDER',
+++ 'SUPPRESS',
+++ 'ZERO_OR_MORE',
+++]
+++
+++
+++import copy as _copy
+++import os as _os
+++import re as _re
+++import sys as _sys
+++import textwrap as _textwrap
+++
+++from gettext import gettext as _
+++
+++try:
+++ set
+++except NameError:
+++ # for python < 2.4 compatibility (sets module is there since 2.3):
+++ from sets import Set as set
+++
+++try:
+++ basestring
+++except NameError:
+++ basestring = str
+++
+++try:
+++ sorted
+++except NameError:
+++ # for python < 2.4 compatibility:
+++ def sorted(iterable, reverse=False):
+++ result = list(iterable)
+++ result.sort()
+++ if reverse:
+++ result.reverse()
+++ return result
+++
+++
+++def _callable(obj):
+++ return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
+++
+++
+++SUPPRESS = '==SUPPRESS=='
+++
+++OPTIONAL = '?'
+++ZERO_OR_MORE = '*'
+++ONE_OR_MORE = '+'
+++PARSER = 'A...'
+++REMAINDER = '...'
+++_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
+++
+++# =============================
+++# Utility functions and classes
+++# =============================
+++
+++class _AttributeHolder(object):
+++ """Abstract base class that provides __repr__.
+++
+++ The __repr__ method returns a string in the format::
+++ ClassName(attr=name, attr=name, ...)
+++ The attributes are determined either by a class-level attribute,
+++ '_kwarg_names', or by inspecting the instance __dict__.
+++ """
+++
+++ def __repr__(self):
+++ type_name = type(self).__name__
+++ arg_strings = []
+++ for arg in self._get_args():
+++ arg_strings.append(repr(arg))
+++ for name, value in self._get_kwargs():
+++ arg_strings.append('%s=%r' % (name, value))
+++ return '%s(%s)' % (type_name, ', '.join(arg_strings))
+++
+++ def _get_kwargs(self):
+++ return sorted(self.__dict__.items())
+++
+++ def _get_args(self):
+++ return []
+++
+++
+++def _ensure_value(namespace, name, value):
+++ if getattr(namespace, name, None) is None:
+++ setattr(namespace, name, value)
+++ return getattr(namespace, name)
+++
+++
+++# ===============
+++# Formatting Help
+++# ===============
+++
+++class HelpFormatter(object):
+++ """Formatter for generating usage messages and argument help strings.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def __init__(self,
+++ prog,
+++ indent_increment=2,
+++ max_help_position=24,
+++ width=None):
+++
+++ # default setting for width
+++ if width is None:
+++ try:
+++ width = int(_os.environ['COLUMNS'])
+++ except (KeyError, ValueError):
+++ width = 80
+++ width -= 2
+++
+++ self._prog = prog
+++ self._indent_increment = indent_increment
+++ self._max_help_position = max_help_position
+++ self._width = width
+++
+++ self._current_indent = 0
+++ self._level = 0
+++ self._action_max_length = 0
+++
+++ self._root_section = self._Section(self, None)
+++ self._current_section = self._root_section
+++
+++ self._whitespace_matcher = _re.compile(r'\s+')
+++ self._long_break_matcher = _re.compile(r'\n\n\n+')
+++
+++ # ===============================
+++ # Section and indentation methods
+++ # ===============================
+++ def _indent(self):
+++ self._current_indent += self._indent_increment
+++ self._level += 1
+++
+++ def _dedent(self):
+++ self._current_indent -= self._indent_increment
+++ assert self._current_indent >= 0, 'Indent decreased below 0.'
+++ self._level -= 1
+++
+++ class _Section(object):
+++
+++ def __init__(self, formatter, parent, heading=None):
+++ self.formatter = formatter
+++ self.parent = parent
+++ self.heading = heading
+++ self.items = []
+++
+++ def format_help(self):
+++ # format the indented section
+++ if self.parent is not None:
+++ self.formatter._indent()
+++ join = self.formatter._join_parts
+++ for func, args in self.items:
+++ func(*args)
+++ item_help = join([func(*args) for func, args in self.items])
+++ if self.parent is not None:
+++ self.formatter._dedent()
+++
+++ # return nothing if the section was empty
+++ if not item_help:
+++ return ''
+++
+++ # add the heading if the section was non-empty
+++ if self.heading is not SUPPRESS and self.heading is not None:
+++ current_indent = self.formatter._current_indent
+++ heading = '%*s%s:\n' % (current_indent, '', self.heading)
+++ else:
+++ heading = ''
+++
+++ # join the section-initial newline, the heading and the help
+++ return join(['\n', heading, item_help, '\n'])
+++
+++ def _add_item(self, func, args):
+++ self._current_section.items.append((func, args))
+++
+++ # ========================
+++ # Message building methods
+++ # ========================
+++ def start_section(self, heading):
+++ self._indent()
+++ section = self._Section(self, self._current_section, heading)
+++ self._add_item(section.format_help, [])
+++ self._current_section = section
+++
+++ def end_section(self):
+++ self._current_section = self._current_section.parent
+++ self._dedent()
+++
+++ def add_text(self, text):
+++ if text is not SUPPRESS and text is not None:
+++ self._add_item(self._format_text, [text])
+++
+++ def add_usage(self, usage, actions, groups, prefix=None):
+++ if usage is not SUPPRESS:
+++ args = usage, actions, groups, prefix
+++ self._add_item(self._format_usage, args)
+++
+++ def add_argument(self, action):
+++ if action.help is not SUPPRESS:
+++
+++ # find all invocations
+++ get_invocation = self._format_action_invocation
+++ invocations = [get_invocation(action)]
+++ for subaction in self._iter_indented_subactions(action):
+++ invocations.append(get_invocation(subaction))
+++
+++ # update the maximum item length
+++ invocation_length = max([len(s) for s in invocations])
+++ action_length = invocation_length + self._current_indent
+++ self._action_max_length = max(self._action_max_length,
+++ action_length)
+++
+++ # add the item to the list
+++ self._add_item(self._format_action, [action])
+++
+++ def add_arguments(self, actions):
+++ for action in actions:
+++ self.add_argument(action)
+++
+++ # =======================
+++ # Help-formatting methods
+++ # =======================
+++ def format_help(self):
+++ help = self._root_section.format_help()
+++ if help:
+++ help = self._long_break_matcher.sub('\n\n', help)
+++ help = help.strip('\n') + '\n'
+++ return help
+++
+++ def _join_parts(self, part_strings):
+++ return ''.join([part
+++ for part in part_strings
+++ if part and part is not SUPPRESS])
+++
+++ def _format_usage(self, usage, actions, groups, prefix):
+++ if prefix is None:
+++ prefix = _('usage: ')
+++
+++ # if usage is specified, use that
+++ if usage is not None:
+++ usage = usage % dict(prog=self._prog)
+++
+++ # if no optionals or positionals are available, usage is just prog
+++ elif usage is None and not actions:
+++ usage = '%(prog)s' % dict(prog=self._prog)
+++
+++ # if optionals and positionals are available, calculate usage
+++ elif usage is None:
+++ prog = '%(prog)s' % dict(prog=self._prog)
+++
+++ # split optionals from positionals
+++ optionals = []
+++ positionals = []
+++ for action in actions:
+++ if action.option_strings:
+++ optionals.append(action)
+++ else:
+++ positionals.append(action)
+++
+++ # build full usage string
+++ format = self._format_actions_usage
+++ action_usage = format(optionals + positionals, groups)
+++ usage = ' '.join([s for s in [prog, action_usage] if s])
+++
+++ # wrap the usage parts if it's too long
+++ text_width = self._width - self._current_indent
+++ if len(prefix) + len(usage) > text_width:
+++
+++ # break usage into wrappable parts
+++ part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
+++ opt_usage = format(optionals, groups)
+++ pos_usage = format(positionals, groups)
+++ opt_parts = _re.findall(part_regexp, opt_usage)
+++ pos_parts = _re.findall(part_regexp, pos_usage)
+++ assert ' '.join(opt_parts) == opt_usage
+++ assert ' '.join(pos_parts) == pos_usage
+++
+++ # helper for wrapping lines
+++ def get_lines(parts, indent, prefix=None):
+++ lines = []
+++ line = []
+++ if prefix is not None:
+++ line_len = len(prefix) - 1
+++ else:
+++ line_len = len(indent) - 1
+++ for part in parts:
+++ if line_len + 1 + len(part) > text_width:
+++ lines.append(indent + ' '.join(line))
+++ line = []
+++ line_len = len(indent) - 1
+++ line.append(part)
+++ line_len += len(part) + 1
+++ if line:
+++ lines.append(indent + ' '.join(line))
+++ if prefix is not None:
+++ lines[0] = lines[0][len(indent):]
+++ return lines
+++
+++ # if prog is short, follow it with optionals or positionals
+++ if len(prefix) + len(prog) <= 0.75 * text_width:
+++ indent = ' ' * (len(prefix) + len(prog) + 1)
+++ if opt_parts:
+++ lines = get_lines([prog] + opt_parts, indent, prefix)
+++ lines.extend(get_lines(pos_parts, indent))
+++ elif pos_parts:
+++ lines = get_lines([prog] + pos_parts, indent, prefix)
+++ else:
+++ lines = [prog]
+++
+++ # if prog is long, put it on its own line
+++ else:
+++ indent = ' ' * len(prefix)
+++ parts = opt_parts + pos_parts
+++ lines = get_lines(parts, indent)
+++ if len(lines) > 1:
+++ lines = []
+++ lines.extend(get_lines(opt_parts, indent))
+++ lines.extend(get_lines(pos_parts, indent))
+++ lines = [prog] + lines
+++
+++ # join lines into usage
+++ usage = '\n'.join(lines)
+++
+++ # prefix with 'usage:'
+++ return '%s%s\n\n' % (prefix, usage)
+++
+++ def _format_actions_usage(self, actions, groups):
+++ # find group indices and identify actions in groups
+++ group_actions = set()
+++ inserts = {}
+++ for group in groups:
+++ try:
+++ start = actions.index(group._group_actions[0])
+++ except ValueError:
+++ continue
+++ else:
+++ end = start + len(group._group_actions)
+++ if actions[start:end] == group._group_actions:
+++ for action in group._group_actions:
+++ group_actions.add(action)
+++ if not group.required:
+++ if start in inserts:
+++ inserts[start] += ' ['
+++ else:
+++ inserts[start] = '['
+++ inserts[end] = ']'
+++ else:
+++ if start in inserts:
+++ inserts[start] += ' ('
+++ else:
+++ inserts[start] = '('
+++ inserts[end] = ')'
+++ for i in range(start + 1, end):
+++ inserts[i] = '|'
+++
+++ # collect all actions format strings
+++ parts = []
+++ for i, action in enumerate(actions):
+++
+++ # suppressed arguments are marked with None
+++ # remove | separators for suppressed arguments
+++ if action.help is SUPPRESS:
+++ parts.append(None)
+++ if inserts.get(i) == '|':
+++ inserts.pop(i)
+++ elif inserts.get(i + 1) == '|':
+++ inserts.pop(i + 1)
+++
+++ # produce all arg strings
+++ elif not action.option_strings:
+++ part = self._format_args(action, action.dest)
+++
+++ # if it's in a group, strip the outer []
+++ if action in group_actions:
+++ if part[0] == '[' and part[-1] == ']':
+++ part = part[1:-1]
+++
+++ # add the action string to the list
+++ parts.append(part)
+++
+++ # produce the first way to invoke the option in brackets
+++ else:
+++ option_string = action.option_strings[0]
+++
+++ # if the Optional doesn't take a value, format is:
+++ # -s or --long
+++ if action.nargs == 0:
+++ part = '%s' % option_string
+++
+++ # if the Optional takes a value, format is:
+++ # -s ARGS or --long ARGS
+++ else:
+++ default = action.dest.upper()
+++ args_string = self._format_args(action, default)
+++ part = '%s %s' % (option_string, args_string)
+++
+++ # make it look optional if it's not required or in a group
+++ if not action.required and action not in group_actions:
+++ part = '[%s]' % part
+++
+++ # add the action string to the list
+++ parts.append(part)
+++
+++ # insert things at the necessary indices
+++ for i in sorted(inserts, reverse=True):
+++ parts[i:i] = [inserts[i]]
+++
+++ # join all the action items with spaces
+++ text = ' '.join([item for item in parts if item is not None])
+++
+++ # clean up separators for mutually exclusive groups
+++ open = r'[\[(]'
+++ close = r'[\])]'
+++ text = _re.sub(r'(%s) ' % open, r'\1', text)
+++ text = _re.sub(r' (%s)' % close, r'\1', text)
+++ text = _re.sub(r'%s *%s' % (open, close), r'', text)
+++ text = _re.sub(r'\(([^|]*)\)', r'\1', text)
+++ text = text.strip()
+++
+++ # return the text
+++ return text
+++
+++ def _format_text(self, text):
+++ if '%(prog)' in text:
+++ text = text % dict(prog=self._prog)
+++ text_width = self._width - self._current_indent
+++ indent = ' ' * self._current_indent
+++ return self._fill_text(text, text_width, indent) + '\n\n'
+++
+++ def _format_action(self, action):
+++ # determine the required width and the entry label
+++ help_position = min(self._action_max_length + 2,
+++ self._max_help_position)
+++ help_width = self._width - help_position
+++ action_width = help_position - self._current_indent - 2
+++ action_header = self._format_action_invocation(action)
+++
+++ # ho nelp; start on same line and add a final newline
+++ if not action.help:
+++ tup = self._current_indent, '', action_header
+++ action_header = '%*s%s\n' % tup
+++
+++ # short action name; start on the same line and pad two spaces
+++ elif len(action_header) <= action_width:
+++ tup = self._current_indent, '', action_width, action_header
+++ action_header = '%*s%-*s ' % tup
+++ indent_first = 0
+++
+++ # long action name; start on the next line
+++ else:
+++ tup = self._current_indent, '', action_header
+++ action_header = '%*s%s\n' % tup
+++ indent_first = help_position
+++
+++ # collect the pieces of the action help
+++ parts = [action_header]
+++
+++ # if there was help for the action, add lines of help text
+++ if action.help:
+++ help_text = self._expand_help(action)
+++ help_lines = self._split_lines(help_text, help_width)
+++ parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
+++ for line in help_lines[1:]:
+++ parts.append('%*s%s\n' % (help_position, '', line))
+++
+++ # or add a newline if the description doesn't end with one
+++ elif not action_header.endswith('\n'):
+++ parts.append('\n')
+++
+++ # if there are any sub-actions, add their help as well
+++ for subaction in self._iter_indented_subactions(action):
+++ parts.append(self._format_action(subaction))
+++
+++ # return a single string
+++ return self._join_parts(parts)
+++
+++ def _format_action_invocation(self, action):
+++ if not action.option_strings:
+++ metavar, = self._metavar_formatter(action, action.dest)(1)
+++ return metavar
+++
+++ else:
+++ parts = []
+++
+++ # if the Optional doesn't take a value, format is:
+++ # -s, --long
+++ if action.nargs == 0:
+++ parts.extend(action.option_strings)
+++
+++ # if the Optional takes a value, format is:
+++ # -s ARGS, --long ARGS
+++ else:
+++ default = action.dest.upper()
+++ args_string = self._format_args(action, default)
+++ for option_string in action.option_strings:
+++ parts.append('%s %s' % (option_string, args_string))
+++
+++ return ', '.join(parts)
+++
+++ def _metavar_formatter(self, action, default_metavar):
+++ if action.metavar is not None:
+++ result = action.metavar
+++ elif action.choices is not None:
+++ choice_strs = [str(choice) for choice in action.choices]
+++ result = '{%s}' % ','.join(choice_strs)
+++ else:
+++ result = default_metavar
+++
+++ def format(tuple_size):
+++ if isinstance(result, tuple):
+++ return result
+++ else:
+++ return (result, ) * tuple_size
+++ return format
+++
+++ def _format_args(self, action, default_metavar):
+++ get_metavar = self._metavar_formatter(action, default_metavar)
+++ if action.nargs is None:
+++ result = '%s' % get_metavar(1)
+++ elif action.nargs == OPTIONAL:
+++ result = '[%s]' % get_metavar(1)
+++ elif action.nargs == ZERO_OR_MORE:
+++ result = '[%s [%s ...]]' % get_metavar(2)
+++ elif action.nargs == ONE_OR_MORE:
+++ result = '%s [%s ...]' % get_metavar(2)
+++ elif action.nargs == REMAINDER:
+++ result = '...'
+++ elif action.nargs == PARSER:
+++ result = '%s ...' % get_metavar(1)
+++ else:
+++ formats = ['%s' for _ in range(action.nargs)]
+++ result = ' '.join(formats) % get_metavar(action.nargs)
+++ return result
+++
+++ def _expand_help(self, action):
+++ params = dict(vars(action), prog=self._prog)
+++ for name in list(params):
+++ if params[name] is SUPPRESS:
+++ del params[name]
+++ for name in list(params):
+++ if hasattr(params[name], '__name__'):
+++ params[name] = params[name].__name__
+++ if params.get('choices') is not None:
+++ choices_str = ', '.join([str(c) for c in params['choices']])
+++ params['choices'] = choices_str
+++ return self._get_help_string(action) % params
+++
+++ def _iter_indented_subactions(self, action):
+++ try:
+++ get_subactions = action._get_subactions
+++ except AttributeError:
+++ pass
+++ else:
+++ self._indent()
+++ for subaction in get_subactions():
+++ yield subaction
+++ self._dedent()
+++
+++ def _split_lines(self, text, width):
+++ text = self._whitespace_matcher.sub(' ', text).strip()
+++ return _textwrap.wrap(text, width)
+++
+++ def _fill_text(self, text, width, indent):
+++ text = self._whitespace_matcher.sub(' ', text).strip()
+++ return _textwrap.fill(text, width, initial_indent=indent,
+++ subsequent_indent=indent)
+++
+++ def _get_help_string(self, action):
+++ return action.help
+++
+++
+++class RawDescriptionHelpFormatter(HelpFormatter):
+++ """Help message formatter which retains any formatting in descriptions.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _fill_text(self, text, width, indent):
+++ return ''.join([indent + line for line in text.splitlines(True)])
+++
+++
+++class RawTextHelpFormatter(RawDescriptionHelpFormatter):
+++ """Help message formatter which retains formatting of all help text.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _split_lines(self, text, width):
+++ return text.splitlines()
+++
+++
+++class ArgumentDefaultsHelpFormatter(HelpFormatter):
+++ """Help message formatter which adds default values to argument help.
+++
+++ Only the name of this class is considered a public API. All the methods
+++ provided by the class are considered an implementation detail.
+++ """
+++
+++ def _get_help_string(self, action):
+++ help = action.help
+++ if '%(default)' not in action.help:
+++ if action.default is not SUPPRESS:
+++ defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
+++ if action.option_strings or action.nargs in defaulting_nargs:
+++ help += ' (default: %(default)s)'
+++ return help
+++
+++
+++# =====================
+++# Options and Arguments
+++# =====================
+++
+++def _get_action_name(argument):
+++ if argument is None:
+++ return None
+++ elif argument.option_strings:
+++ return '/'.join(argument.option_strings)
+++ elif argument.metavar not in (None, SUPPRESS):
+++ return argument.metavar
+++ elif argument.dest not in (None, SUPPRESS):
+++ return argument.dest
+++ else:
+++ return None
+++
+++
+++class ArgumentError(Exception):
+++ """An error from creating or using an argument (optional or positional).
+++
+++ The string value of this exception is the message, augmented with
+++ information about the argument that caused it.
+++ """
+++
+++ def __init__(self, argument, message):
+++ self.argument_name = _get_action_name(argument)
+++ self.message = message
+++
+++ def __str__(self):
+++ if self.argument_name is None:
+++ format = '%(message)s'
+++ else:
+++ format = 'argument %(argument_name)s: %(message)s'
+++ return format % dict(message=self.message,
+++ argument_name=self.argument_name)
+++
+++
+++class ArgumentTypeError(Exception):
+++ """An error from trying to convert a command line string to a type."""
+++ pass
+++
+++
+++# ==============
+++# Action classes
+++# ==============
+++
+++class Action(_AttributeHolder):
+++ """Information about how to convert command line strings to Python objects.
+++
+++ Action objects are used by an ArgumentParser to represent the information
+++ needed to parse a single argument from one or more strings from the
+++ command line. The keyword arguments to the Action constructor are also
+++ all attributes of Action instances.
+++
+++ Keyword Arguments:
+++
+++ - option_strings -- A list of command-line option strings which
+++ should be associated with this action.
+++
+++ - dest -- The name of the attribute to hold the created object(s)
+++
+++ - nargs -- The number of command-line arguments that should be
+++ consumed. By default, one argument will be consumed and a single
+++ value will be produced. Other values include:
+++ - N (an integer) consumes N arguments (and produces a list)
+++ - '?' consumes zero or one arguments
+++ - '*' consumes zero or more arguments (and produces a list)
+++ - '+' consumes one or more arguments (and produces a list)
+++ Note that the difference between the default and nargs=1 is that
+++ with the default, a single value will be produced, while with
+++ nargs=1, a list containing a single value will be produced.
+++
+++ - const -- The value to be produced if the option is specified and the
+++ option uses an action that takes no values.
+++
+++ - default -- The value to be produced if the option is not specified.
+++
+++ - type -- The type which the command-line arguments should be converted
+++ to, should be one of 'string', 'int', 'float', 'complex' or a
+++ callable object that accepts a single string argument. If None,
+++ 'string' is assumed.
+++
+++ - choices -- A container of values that should be allowed. If not None,
+++ after a command-line argument has been converted to the appropriate
+++ type, an exception will be raised if it is not a member of this
+++ collection.
+++
+++ - required -- True if the action must always be specified at the
+++ command line. This is only meaningful for optional command-line
+++ arguments.
+++
+++ - help -- The help string describing the argument.
+++
+++ - metavar -- The name to be used for the option's argument with the
+++ help string. If None, the 'dest' value will be used as the name.
+++ """
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ self.option_strings = option_strings
+++ self.dest = dest
+++ self.nargs = nargs
+++ self.const = const
+++ self.default = default
+++ self.type = type
+++ self.choices = choices
+++ self.required = required
+++ self.help = help
+++ self.metavar = metavar
+++
+++ def _get_kwargs(self):
+++ names = [
+++ 'option_strings',
+++ 'dest',
+++ 'nargs',
+++ 'const',
+++ 'default',
+++ 'type',
+++ 'choices',
+++ 'help',
+++ 'metavar',
+++ ]
+++ return [(name, getattr(self, name)) for name in names]
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ raise NotImplementedError(_('.__call__() not defined'))
+++
+++
+++class _StoreAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ if nargs == 0:
+++ raise ValueError('nargs for store actions must be > 0; if you '
+++ 'have nothing to store, actions such as store '
+++ 'true or store const may be more appropriate')
+++ if const is not None and nargs != OPTIONAL:
+++ raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+++ super(_StoreAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=nargs,
+++ const=const,
+++ default=default,
+++ type=type,
+++ choices=choices,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ setattr(namespace, self.dest, values)
+++
+++
+++class _StoreConstAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ const,
+++ default=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ super(_StoreConstAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ const=const,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ setattr(namespace, self.dest, self.const)
+++
+++
+++class _StoreTrueAction(_StoreConstAction):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=False,
+++ required=False,
+++ help=None):
+++ super(_StoreTrueAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ const=True,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++
+++class _StoreFalseAction(_StoreConstAction):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=True,
+++ required=False,
+++ help=None):
+++ super(_StoreFalseAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ const=False,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++
+++class _AppendAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ nargs=None,
+++ const=None,
+++ default=None,
+++ type=None,
+++ choices=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ if nargs == 0:
+++ raise ValueError('nargs for append actions must be > 0; if arg '
+++ 'strings are not supplying the value to append, '
+++ 'the append const action may be more appropriate')
+++ if const is not None and nargs != OPTIONAL:
+++ raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+++ super(_AppendAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=nargs,
+++ const=const,
+++ default=default,
+++ type=type,
+++ choices=choices,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ items = _copy.copy(_ensure_value(namespace, self.dest, []))
+++ items.append(values)
+++ setattr(namespace, self.dest, items)
+++
+++
+++class _AppendConstAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ const,
+++ default=None,
+++ required=False,
+++ help=None,
+++ metavar=None):
+++ super(_AppendConstAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ const=const,
+++ default=default,
+++ required=required,
+++ help=help,
+++ metavar=metavar)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ items = _copy.copy(_ensure_value(namespace, self.dest, []))
+++ items.append(self.const)
+++ setattr(namespace, self.dest, items)
+++
+++
+++class _CountAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest,
+++ default=None,
+++ required=False,
+++ help=None):
+++ super(_CountAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=0,
+++ default=default,
+++ required=required,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ new_count = _ensure_value(namespace, self.dest, 0) + 1
+++ setattr(namespace, self.dest, new_count)
+++
+++
+++class _HelpAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ dest=SUPPRESS,
+++ default=SUPPRESS,
+++ help=None):
+++ super(_HelpAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ default=default,
+++ nargs=0,
+++ help=help)
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ parser.print_help()
+++ parser.exit()
+++
+++
+++class _VersionAction(Action):
+++
+++ def __init__(self,
+++ option_strings,
+++ version=None,
+++ dest=SUPPRESS,
+++ default=SUPPRESS,
+++ help="show program's version number and exit"):
+++ super(_VersionAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ default=default,
+++ nargs=0,
+++ help=help)
+++ self.version = version
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ version = self.version
+++ if version is None:
+++ version = parser.version
+++ formatter = parser._get_formatter()
+++ formatter.add_text(version)
+++ parser.exit(message=formatter.format_help())
+++
+++
+++class _SubParsersAction(Action):
+++
+++ class _ChoicesPseudoAction(Action):
+++
+++ def __init__(self, name, help):
+++ sup = super(_SubParsersAction._ChoicesPseudoAction, self)
+++ sup.__init__(option_strings=[], dest=name, help=help)
+++
+++ def __init__(self,
+++ option_strings,
+++ prog,
+++ parser_class,
+++ dest=SUPPRESS,
+++ help=None,
+++ metavar=None):
+++
+++ self._prog_prefix = prog
+++ self._parser_class = parser_class
+++ self._name_parser_map = {}
+++ self._choices_actions = []
+++
+++ super(_SubParsersAction, self).__init__(
+++ option_strings=option_strings,
+++ dest=dest,
+++ nargs=PARSER,
+++ choices=self._name_parser_map,
+++ help=help,
+++ metavar=metavar)
+++
+++ def add_parser(self, name, **kwargs):
+++ # set prog from the existing prefix
+++ if kwargs.get('prog') is None:
+++ kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
+++
+++ # create a pseudo-action to hold the choice help
+++ if 'help' in kwargs:
+++ help = kwargs.pop('help')
+++ choice_action = self._ChoicesPseudoAction(name, help)
+++ self._choices_actions.append(choice_action)
+++
+++ # create the parser and add it to the map
+++ parser = self._parser_class(**kwargs)
+++ self._name_parser_map[name] = parser
+++ return parser
+++
+++ def _get_subactions(self):
+++ return self._choices_actions
+++
+++ def __call__(self, parser, namespace, values, option_string=None):
+++ parser_name = values[0]
+++ arg_strings = values[1:]
+++
+++ # set the parser name if requested
+++ if self.dest is not SUPPRESS:
+++ setattr(namespace, self.dest, parser_name)
+++
+++ # select the parser
+++ try:
+++ parser = self._name_parser_map[parser_name]
+++ except KeyError:
+++ tup = parser_name, ', '.join(self._name_parser_map)
+++ msg = _('unknown parser %r (choices: %s)' % tup)
+++ raise ArgumentError(self, msg)
+++
+++ # parse all the remaining options into the namespace
+++ # store any unrecognized options on the object, so that the top
+++ # level parser can decide what to do with them
+++ namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
+++ if arg_strings:
+++ vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
+++ getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
+++
+++
+++# ==============
+++# Type classes
+++# ==============
+++
+++class FileType(object):
+++ """Factory for creating file object types
+++
+++ Instances of FileType are typically passed as type= arguments to the
+++ ArgumentParser add_argument() method.
+++
+++ Keyword Arguments:
+++ - mode -- A string indicating how the file is to be opened. Accepts the
+++ same values as the builtin open() function.
+++ - bufsize -- The file's desired buffer size. Accepts the same values as
+++ the builtin open() function.
+++ """
+++
+++ def __init__(self, mode='r', bufsize=None):
+++ self._mode = mode
+++ self._bufsize = bufsize
+++
+++ def __call__(self, string):
+++ # the special argument "-" means sys.std{in,out}
+++ if string == '-':
+++ if 'r' in self._mode:
+++ return _sys.stdin
+++ elif 'w' in self._mode:
+++ return _sys.stdout
+++ else:
+++ msg = _('argument "-" with mode %r' % self._mode)
+++ raise ValueError(msg)
+++
+++ # all other arguments are used as file names
+++ if self._bufsize:
+++ return open(string, self._mode, self._bufsize)
+++ else:
+++ return open(string, self._mode)
+++
+++ def __repr__(self):
+++ args = [self._mode, self._bufsize]
+++ args_str = ', '.join([repr(arg) for arg in args if arg is not None])
+++ return '%s(%s)' % (type(self).__name__, args_str)
+++
+++# ===========================
+++# Optional and Positional Parsing
+++# ===========================
+++
+++class Namespace(_AttributeHolder):
+++ """Simple object for storing attributes.
+++
+++ Implements equality by attribute names and values, and provides a simple
+++ string representation.
+++ """
+++
+++ def __init__(self, **kwargs):
+++ for name in kwargs:
+++ setattr(self, name, kwargs[name])
+++
+++ __hash__ = None
+++
+++ def __eq__(self, other):
+++ return vars(self) == vars(other)
+++
+++ def __ne__(self, other):
+++ return not (self == other)
+++
+++ def __contains__(self, key):
+++ return key in self.__dict__
+++
+++
+++class _ActionsContainer(object):
+++
+++ def __init__(self,
+++ description,
+++ prefix_chars,
+++ argument_default,
+++ conflict_handler):
+++ super(_ActionsContainer, self).__init__()
+++
+++ self.description = description
+++ self.argument_default = argument_default
+++ self.prefix_chars = prefix_chars
+++ self.conflict_handler = conflict_handler
+++
+++ # set up registries
+++ self._registries = {}
+++
+++ # register actions
+++ self.register('action', None, _StoreAction)
+++ self.register('action', 'store', _StoreAction)
+++ self.register('action', 'store_const', _StoreConstAction)
+++ self.register('action', 'store_true', _StoreTrueAction)
+++ self.register('action', 'store_false', _StoreFalseAction)
+++ self.register('action', 'append', _AppendAction)
+++ self.register('action', 'append_const', _AppendConstAction)
+++ self.register('action', 'count', _CountAction)
+++ self.register('action', 'help', _HelpAction)
+++ self.register('action', 'version', _VersionAction)
+++ self.register('action', 'parsers', _SubParsersAction)
+++
+++ # raise an exception if the conflict handler is invalid
+++ self._get_handler()
+++
+++ # action storage
+++ self._actions = []
+++ self._option_string_actions = {}
+++
+++ # groups
+++ self._action_groups = []
+++ self._mutually_exclusive_groups = []
+++
+++ # defaults storage
+++ self._defaults = {}
+++
+++ # determines whether an "option" looks like a negative number
+++ self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
+++
+++ # whether or not there are any optionals that look like negative
+++ # numbers -- uses a list so it can be shared and edited
+++ self._has_negative_number_optionals = []
+++
+++ # ====================
+++ # Registration methods
+++ # ====================
+++ def register(self, registry_name, value, object):
+++ registry = self._registries.setdefault(registry_name, {})
+++ registry[value] = object
+++
+++ def _registry_get(self, registry_name, value, default=None):
+++ return self._registries[registry_name].get(value, default)
+++
+++ # ==================================
+++ # Namespace default accessor methods
+++ # ==================================
+++ def set_defaults(self, **kwargs):
+++ self._defaults.update(kwargs)
+++
+++ # if these defaults match any existing arguments, replace
+++ # the previous default on the object with the new one
+++ for action in self._actions:
+++ if action.dest in kwargs:
+++ action.default = kwargs[action.dest]
+++
+++ def get_default(self, dest):
+++ for action in self._actions:
+++ if action.dest == dest and action.default is not None:
+++ return action.default
+++ return self._defaults.get(dest, None)
+++
+++
+++ # =======================
+++ # Adding argument actions
+++ # =======================
+++ def add_argument(self, *args, **kwargs):
+++ """
+++ add_argument(dest, ..., name=value, ...)
+++ add_argument(option_string, option_string, ..., name=value, ...)
+++ """
+++
+++ # if no positional args are supplied or only one is supplied and
+++ # it doesn't look like an option string, parse a positional
+++ # argument
+++ chars = self.prefix_chars
+++ if not args or len(args) == 1 and args[0][0] not in chars:
+++ if args and 'dest' in kwargs:
+++ raise ValueError('dest supplied twice for positional argument')
+++ kwargs = self._get_positional_kwargs(*args, **kwargs)
+++
+++ # otherwise, we're adding an optional argument
+++ else:
+++ kwargs = self._get_optional_kwargs(*args, **kwargs)
+++
+++ # if no default was supplied, use the parser-level default
+++ if 'default' not in kwargs:
+++ dest = kwargs['dest']
+++ if dest in self._defaults:
+++ kwargs['default'] = self._defaults[dest]
+++ elif self.argument_default is not None:
+++ kwargs['default'] = self.argument_default
+++
+++ # create the action object, and add it to the parser
+++ action_class = self._pop_action_class(kwargs)
+++ if not _callable(action_class):
+++ raise ValueError('unknown action "%s"' % action_class)
+++ action = action_class(**kwargs)
+++
+++ # raise an error if the action type is not callable
+++ type_func = self._registry_get('type', action.type, action.type)
+++ if not _callable(type_func):
+++ raise ValueError('%r is not callable' % type_func)
+++
+++ return self._add_action(action)
+++
+++ def add_argument_group(self, *args, **kwargs):
+++ group = _ArgumentGroup(self, *args, **kwargs)
+++ self._action_groups.append(group)
+++ return group
+++
+++ def add_mutually_exclusive_group(self, **kwargs):
+++ group = _MutuallyExclusiveGroup(self, **kwargs)
+++ self._mutually_exclusive_groups.append(group)
+++ return group
+++
+++ def _add_action(self, action):
+++ # resolve any conflicts
+++ self._check_conflict(action)
+++
+++ # add to actions list
+++ self._actions.append(action)
+++ action.container = self
+++
+++ # index the action by any option strings it has
+++ for option_string in action.option_strings:
+++ self._option_string_actions[option_string] = action
+++
+++ # set the flag if any option strings look like negative numbers
+++ for option_string in action.option_strings:
+++ if self._negative_number_matcher.match(option_string):
+++ if not self._has_negative_number_optionals:
+++ self._has_negative_number_optionals.append(True)
+++
+++ # return the created action
+++ return action
+++
+++ def _remove_action(self, action):
+++ self._actions.remove(action)
+++
+++ def _add_container_actions(self, container):
+++ # collect groups by titles
+++ title_group_map = {}
+++ for group in self._action_groups:
+++ if group.title in title_group_map:
+++ msg = _('cannot merge actions - two groups are named %r')
+++ raise ValueError(msg % (group.title))
+++ title_group_map[group.title] = group
+++
+++ # map each action to its group
+++ group_map = {}
+++ for group in container._action_groups:
+++
+++ # if a group with the title exists, use that, otherwise
+++ # create a new group matching the container's group
+++ if group.title not in title_group_map:
+++ title_group_map[group.title] = self.add_argument_group(
+++ title=group.title,
+++ description=group.description,
+++ conflict_handler=group.conflict_handler)
+++
+++ # map the actions to their new group
+++ for action in group._group_actions:
+++ group_map[action] = title_group_map[group.title]
+++
+++ # add container's mutually exclusive groups
+++ # NOTE: if add_mutually_exclusive_group ever gains title= and
+++ # description= then this code will need to be expanded as above
+++ for group in container._mutually_exclusive_groups:
+++ mutex_group = self.add_mutually_exclusive_group(
+++ required=group.required)
+++
+++ # map the actions to their new mutex group
+++ for action in group._group_actions:
+++ group_map[action] = mutex_group
+++
+++ # add all actions to this container or their group
+++ for action in container._actions:
+++ group_map.get(action, self)._add_action(action)
+++
+++ def _get_positional_kwargs(self, dest, **kwargs):
+++ # make sure required is not specified
+++ if 'required' in kwargs:
+++ msg = _("'required' is an invalid argument for positionals")
+++ raise TypeError(msg)
+++
+++ # mark positional arguments as required if at least one is
+++ # always required
+++ if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
+++ kwargs['required'] = True
+++ if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
+++ kwargs['required'] = True
+++
+++ # return the keyword arguments with no option strings
+++ return dict(kwargs, dest=dest, option_strings=[])
+++
+++ def _get_optional_kwargs(self, *args, **kwargs):
+++ # determine short and long option strings
+++ option_strings = []
+++ long_option_strings = []
+++ for option_string in args:
+++ # error on strings that don't start with an appropriate prefix
+++ if not option_string[0] in self.prefix_chars:
+++ msg = _('invalid option string %r: '
+++ 'must start with a character %r')
+++ tup = option_string, self.prefix_chars
+++ raise ValueError(msg % tup)
+++
+++ # strings starting with two prefix characters are long options
+++ option_strings.append(option_string)
+++ if option_string[0] in self.prefix_chars:
+++ if len(option_string) > 1:
+++ if option_string[1] in self.prefix_chars:
+++ long_option_strings.append(option_string)
+++
+++ # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
+++ dest = kwargs.pop('dest', None)
+++ if dest is None:
+++ if long_option_strings:
+++ dest_option_string = long_option_strings[0]
+++ else:
+++ dest_option_string = option_strings[0]
+++ dest = dest_option_string.lstrip(self.prefix_chars)
+++ if not dest:
+++ msg = _('dest= is required for options like %r')
+++ raise ValueError(msg % option_string)
+++ dest = dest.replace('-', '_')
+++
+++ # return the updated keyword arguments
+++ return dict(kwargs, dest=dest, option_strings=option_strings)
+++
+++ def _pop_action_class(self, kwargs, default=None):
+++ action = kwargs.pop('action', default)
+++ return self._registry_get('action', action, action)
+++
+++ def _get_handler(self):
+++ # determine function from conflict handler string
+++ handler_func_name = '_handle_conflict_%s' % self.conflict_handler
+++ try:
+++ return getattr(self, handler_func_name)
+++ except AttributeError:
+++ msg = _('invalid conflict_resolution value: %r')
+++ raise ValueError(msg % self.conflict_handler)
+++
+++ def _check_conflict(self, action):
+++
+++ # find all options that conflict with this option
+++ confl_optionals = []
+++ for option_string in action.option_strings:
+++ if option_string in self._option_string_actions:
+++ confl_optional = self._option_string_actions[option_string]
+++ confl_optionals.append((option_string, confl_optional))
+++
+++ # resolve any conflicts
+++ if confl_optionals:
+++ conflict_handler = self._get_handler()
+++ conflict_handler(action, confl_optionals)
+++
+++ def _handle_conflict_error(self, action, conflicting_actions):
+++ message = _('conflicting option string(s): %s')
+++ conflict_string = ', '.join([option_string
+++ for option_string, action
+++ in conflicting_actions])
+++ raise ArgumentError(action, message % conflict_string)
+++
+++ def _handle_conflict_resolve(self, action, conflicting_actions):
+++
+++ # remove all conflicting options
+++ for option_string, action in conflicting_actions:
+++
+++ # remove the conflicting option
+++ action.option_strings.remove(option_string)
+++ self._option_string_actions.pop(option_string, None)
+++
+++ # if the option now has no option string, remove it from the
+++ # container holding it
+++ if not action.option_strings:
+++ action.container._remove_action(action)
+++
+++
+++class _ArgumentGroup(_ActionsContainer):
+++
+++ def __init__(self, container, title=None, description=None, **kwargs):
+++ # add any missing keyword arguments by checking the container
+++ update = kwargs.setdefault
+++ update('conflict_handler', container.conflict_handler)
+++ update('prefix_chars', container.prefix_chars)
+++ update('argument_default', container.argument_default)
+++ super_init = super(_ArgumentGroup, self).__init__
+++ super_init(description=description, **kwargs)
+++
+++ # group attributes
+++ self.title = title
+++ self._group_actions = []
+++
+++ # share most attributes with the container
+++ self._registries = container._registries
+++ self._actions = container._actions
+++ self._option_string_actions = container._option_string_actions
+++ self._defaults = container._defaults
+++ self._has_negative_number_optionals = \
+++ container._has_negative_number_optionals
+++
+++ def _add_action(self, action):
+++ action = super(_ArgumentGroup, self)._add_action(action)
+++ self._group_actions.append(action)
+++ return action
+++
+++ def _remove_action(self, action):
+++ super(_ArgumentGroup, self)._remove_action(action)
+++ self._group_actions.remove(action)
+++
+++
+++class _MutuallyExclusiveGroup(_ArgumentGroup):
+++
+++ def __init__(self, container, required=False):
+++ super(_MutuallyExclusiveGroup, self).__init__(container)
+++ self.required = required
+++ self._container = container
+++
+++ def _add_action(self, action):
+++ if action.required:
+++ msg = _('mutually exclusive arguments must be optional')
+++ raise ValueError(msg)
+++ action = self._container._add_action(action)
+++ self._group_actions.append(action)
+++ return action
+++
+++ def _remove_action(self, action):
+++ self._container._remove_action(action)
+++ self._group_actions.remove(action)
+++
+++
+++class ArgumentParser(_AttributeHolder, _ActionsContainer):
+++ """Object for parsing command line strings into Python objects.
+++
+++ Keyword Arguments:
+++ - prog -- The name of the program (default: sys.argv[0])
+++ - usage -- A usage message (default: auto-generated from arguments)
+++ - description -- A description of what the program does
+++ - epilog -- Text following the argument descriptions
+++ - parents -- Parsers whose arguments should be copied into this one
+++ - formatter_class -- HelpFormatter class for printing help messages
+++ - prefix_chars -- Characters that prefix optional arguments
+++ - fromfile_prefix_chars -- Characters that prefix files containing
+++ additional arguments
+++ - argument_default -- The default value for all arguments
+++ - conflict_handler -- String indicating how to handle conflicts
+++ - add_help -- Add a -h/-help option
+++ """
+++
+++ def __init__(self,
+++ prog=None,
+++ usage=None,
+++ description=None,
+++ epilog=None,
+++ version=None,
+++ parents=[],
+++ formatter_class=HelpFormatter,
+++ prefix_chars='-',
+++ fromfile_prefix_chars=None,
+++ argument_default=None,
+++ conflict_handler='error',
+++ add_help=True):
+++
+++ if version is not None:
+++ import warnings
+++ warnings.warn(
+++ """The "version" argument to ArgumentParser is deprecated. """
+++ """Please use """
+++ """"add_argument(..., action='version', version="N", ...)" """
+++ """instead""", DeprecationWarning)
+++
+++ superinit = super(ArgumentParser, self).__init__
+++ superinit(description=description,
+++ prefix_chars=prefix_chars,
+++ argument_default=argument_default,
+++ conflict_handler=conflict_handler)
+++
+++ # default setting for prog
+++ if prog is None:
+++ prog = _os.path.basename(_sys.argv[0])
+++
+++ self.prog = prog
+++ self.usage = usage
+++ self.epilog = epilog
+++ self.version = version
+++ self.formatter_class = formatter_class
+++ self.fromfile_prefix_chars = fromfile_prefix_chars
+++ self.add_help = add_help
+++
+++ add_group = self.add_argument_group
+++ self._positionals = add_group(_('positional arguments'))
+++ self._optionals = add_group(_('optional arguments'))
+++ self._subparsers = None
+++
+++ # register types
+++ def identity(string):
+++ return string
+++ self.register('type', None, identity)
+++
+++ # add help and version arguments if necessary
+++ # (using explicit default to override global argument_default)
+++ if '-' in prefix_chars:
+++ default_prefix = '-'
+++ else:
+++ default_prefix = prefix_chars[0]
+++ if self.add_help:
+++ self.add_argument(
+++ default_prefix+'h', default_prefix*2+'help',
+++ action='help', default=SUPPRESS,
+++ help=_('show this help message and exit'))
+++ if self.version:
+++ self.add_argument(
+++ default_prefix+'v', default_prefix*2+'version',
+++ action='version', default=SUPPRESS,
+++ version=self.version,
+++ help=_("show program's version number and exit"))
+++
+++ # add parent arguments and defaults
+++ for parent in parents:
+++ self._add_container_actions(parent)
+++ try:
+++ defaults = parent._defaults
+++ except AttributeError:
+++ pass
+++ else:
+++ self._defaults.update(defaults)
+++
+++ # =======================
+++ # Pretty __repr__ methods
+++ # =======================
+++ def _get_kwargs(self):
+++ names = [
+++ 'prog',
+++ 'usage',
+++ 'description',
+++ 'version',
+++ 'formatter_class',
+++ 'conflict_handler',
+++ 'add_help',
+++ ]
+++ return [(name, getattr(self, name)) for name in names]
+++
+++ # ==================================
+++ # Optional/Positional adding methods
+++ # ==================================
+++ def add_subparsers(self, **kwargs):
+++ if self._subparsers is not None:
+++ self.error(_('cannot have multiple subparser arguments'))
+++
+++ # add the parser class to the arguments if it's not present
+++ kwargs.setdefault('parser_class', type(self))
+++
+++ if 'title' in kwargs or 'description' in kwargs:
+++ title = _(kwargs.pop('title', 'subcommands'))
+++ description = _(kwargs.pop('description', None))
+++ self._subparsers = self.add_argument_group(title, description)
+++ else:
+++ self._subparsers = self._positionals
+++
+++ # prog defaults to the usage message of this parser, skipping
+++ # optional arguments and with no "usage:" prefix
+++ if kwargs.get('prog') is None:
+++ formatter = self._get_formatter()
+++ positionals = self._get_positional_actions()
+++ groups = self._mutually_exclusive_groups
+++ formatter.add_usage(self.usage, positionals, groups, '')
+++ kwargs['prog'] = formatter.format_help().strip()
+++
+++ # create the parsers action and add it to the positionals list
+++ parsers_class = self._pop_action_class(kwargs, 'parsers')
+++ action = parsers_class(option_strings=[], **kwargs)
+++ self._subparsers._add_action(action)
+++
+++ # return the created parsers action
+++ return action
+++
+++ def _add_action(self, action):
+++ if action.option_strings:
+++ self._optionals._add_action(action)
+++ else:
+++ self._positionals._add_action(action)
+++ return action
+++
+++ def _get_optional_actions(self):
+++ return [action
+++ for action in self._actions
+++ if action.option_strings]
+++
+++ def _get_positional_actions(self):
+++ return [action
+++ for action in self._actions
+++ if not action.option_strings]
+++
+++ # =====================================
+++ # Command line argument parsing methods
+++ # =====================================
+++ def parse_args(self, args=None, namespace=None):
+++ args, argv = self.parse_known_args(args, namespace)
+++ if argv:
+++ msg = _('unrecognized arguments: %s')
+++ self.error(msg % ' '.join(argv))
+++ return args
+++
+++ def parse_known_args(self, args=None, namespace=None):
+++ # args default to the system args
+++ if args is None:
+++ args = _sys.argv[1:]
+++
+++ # default Namespace built from parser defaults
+++ if namespace is None:
+++ namespace = Namespace()
+++
+++ # add any action defaults that aren't present
+++ for action in self._actions:
+++ if action.dest is not SUPPRESS:
+++ if not hasattr(namespace, action.dest):
+++ if action.default is not SUPPRESS:
+++ default = action.default
+++ if isinstance(action.default, basestring):
+++ default = self._get_value(action, default)
+++ setattr(namespace, action.dest, default)
+++
+++ # add any parser defaults that aren't present
+++ for dest in self._defaults:
+++ if not hasattr(namespace, dest):
+++ setattr(namespace, dest, self._defaults[dest])
+++
+++ # parse the arguments and exit if there are any errors
+++ try:
+++ namespace, args = self._parse_known_args(args, namespace)
+++ if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
+++ args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
+++ delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
+++ return namespace, args
+++ except ArgumentError:
+++ err = _sys.exc_info()[1]
+++ self.error(str(err))
+++
+++ def _parse_known_args(self, arg_strings, namespace):
+++ # replace arg strings that are file references
+++ if self.fromfile_prefix_chars is not None:
+++ arg_strings = self._read_args_from_files(arg_strings)
+++
+++ # map all mutually exclusive arguments to the other arguments
+++ # they can't occur with
+++ action_conflicts = {}
+++ for mutex_group in self._mutually_exclusive_groups:
+++ group_actions = mutex_group._group_actions
+++ for i, mutex_action in enumerate(mutex_group._group_actions):
+++ conflicts = action_conflicts.setdefault(mutex_action, [])
+++ conflicts.extend(group_actions[:i])
+++ conflicts.extend(group_actions[i + 1:])
+++
+++ # find all option indices, and determine the arg_string_pattern
+++ # which has an 'O' if there is an option at an index,
+++ # an 'A' if there is an argument, or a '-' if there is a '--'
+++ option_string_indices = {}
+++ arg_string_pattern_parts = []
+++ arg_strings_iter = iter(arg_strings)
+++ for i, arg_string in enumerate(arg_strings_iter):
+++
+++ # all args after -- are non-options
+++ if arg_string == '--':
+++ arg_string_pattern_parts.append('-')
+++ for arg_string in arg_strings_iter:
+++ arg_string_pattern_parts.append('A')
+++
+++ # otherwise, add the arg to the arg strings
+++ # and note the index if it was an option
+++ else:
+++ option_tuple = self._parse_optional(arg_string)
+++ if option_tuple is None:
+++ pattern = 'A'
+++ else:
+++ option_string_indices[i] = option_tuple
+++ pattern = 'O'
+++ arg_string_pattern_parts.append(pattern)
+++
+++ # join the pieces together to form the pattern
+++ arg_strings_pattern = ''.join(arg_string_pattern_parts)
+++
+++ # converts arg strings to the appropriate and then takes the action
+++ seen_actions = set()
+++ seen_non_default_actions = set()
+++
+++ def take_action(action, argument_strings, option_string=None):
+++ seen_actions.add(action)
+++ argument_values = self._get_values(action, argument_strings)
+++
+++ # error if this argument is not allowed with other previously
+++ # seen arguments, assuming that actions that use the default
+++ # value don't really count as "present"
+++ if argument_values is not action.default:
+++ seen_non_default_actions.add(action)
+++ for conflict_action in action_conflicts.get(action, []):
+++ if conflict_action in seen_non_default_actions:
+++ msg = _('not allowed with argument %s')
+++ action_name = _get_action_name(conflict_action)
+++ raise ArgumentError(action, msg % action_name)
+++
+++ # take the action if we didn't receive a SUPPRESS value
+++ # (e.g. from a default)
+++ if argument_values is not SUPPRESS:
+++ action(self, namespace, argument_values, option_string)
+++
+++ # function to convert arg_strings into an optional action
+++ def consume_optional(start_index):
+++
+++ # get the optional identified at this index
+++ option_tuple = option_string_indices[start_index]
+++ action, option_string, explicit_arg = option_tuple
+++
+++ # identify additional optionals in the same arg string
+++ # (e.g. -xyz is the same as -x -y -z if no args are required)
+++ match_argument = self._match_argument
+++ action_tuples = []
+++ while True:
+++
+++ # if we found no optional action, skip it
+++ if action is None:
+++ extras.append(arg_strings[start_index])
+++ return start_index + 1
+++
+++ # if there is an explicit argument, try to match the
+++ # optional's string arguments to only this
+++ if explicit_arg is not None:
+++ arg_count = match_argument(action, 'A')
+++
+++ # if the action is a single-dash option and takes no
+++ # arguments, try to parse more single-dash options out
+++ # of the tail of the option string
+++ chars = self.prefix_chars
+++ if arg_count == 0 and option_string[1] not in chars:
+++ action_tuples.append((action, [], option_string))
+++ char = option_string[0]
+++ option_string = char + explicit_arg[0]
+++ new_explicit_arg = explicit_arg[1:] or None
+++ optionals_map = self._option_string_actions
+++ if option_string in optionals_map:
+++ action = optionals_map[option_string]
+++ explicit_arg = new_explicit_arg
+++ else:
+++ msg = _('ignored explicit argument %r')
+++ raise ArgumentError(action, msg % explicit_arg)
+++
+++ # if the action expect exactly one argument, we've
+++ # successfully matched the option; exit the loop
+++ elif arg_count == 1:
+++ stop = start_index + 1
+++ args = [explicit_arg]
+++ action_tuples.append((action, args, option_string))
+++ break
+++
+++ # error if a double-dash option did not use the
+++ # explicit argument
+++ else:
+++ msg = _('ignored explicit argument %r')
+++ raise ArgumentError(action, msg % explicit_arg)
+++
+++ # if there is no explicit argument, try to match the
+++ # optional's string arguments with the following strings
+++ # if successful, exit the loop
+++ else:
+++ start = start_index + 1
+++ selected_patterns = arg_strings_pattern[start:]
+++ arg_count = match_argument(action, selected_patterns)
+++ stop = start + arg_count
+++ args = arg_strings[start:stop]
+++ action_tuples.append((action, args, option_string))
+++ break
+++
+++ # add the Optional to the list and return the index at which
+++ # the Optional's string args stopped
+++ assert action_tuples
+++ for action, args, option_string in action_tuples:
+++ take_action(action, args, option_string)
+++ return stop
+++
+++ # the list of Positionals left to be parsed; this is modified
+++ # by consume_positionals()
+++ positionals = self._get_positional_actions()
+++
+++ # function to convert arg_strings into positional actions
+++ def consume_positionals(start_index):
+++ # match as many Positionals as possible
+++ match_partial = self._match_arguments_partial
+++ selected_pattern = arg_strings_pattern[start_index:]
+++ arg_counts = match_partial(positionals, selected_pattern)
+++
+++ # slice off the appropriate arg strings for each Positional
+++ # and add the Positional and its args to the list
+++ for action, arg_count in zip(positionals, arg_counts):
+++ args = arg_strings[start_index: start_index + arg_count]
+++ start_index += arg_count
+++ take_action(action, args)
+++
+++ # slice off the Positionals that we just parsed and return the
+++ # index at which the Positionals' string args stopped
+++ positionals[:] = positionals[len(arg_counts):]
+++ return start_index
+++
+++ # consume Positionals and Optionals alternately, until we have
+++ # passed the last option string
+++ extras = []
+++ start_index = 0
+++ if option_string_indices:
+++ max_option_string_index = max(option_string_indices)
+++ else:
+++ max_option_string_index = -1
+++ while start_index <= max_option_string_index:
+++
+++ # consume any Positionals preceding the next option
+++ next_option_string_index = min([
+++ index
+++ for index in option_string_indices
+++ if index >= start_index])
+++ if start_index != next_option_string_index:
+++ positionals_end_index = consume_positionals(start_index)
+++
+++ # only try to parse the next optional if we didn't consume
+++ # the option string during the positionals parsing
+++ if positionals_end_index > start_index:
+++ start_index = positionals_end_index
+++ continue
+++ else:
+++ start_index = positionals_end_index
+++
+++ # if we consumed all the positionals we could and we're not
+++ # at the index of an option string, there were extra arguments
+++ if start_index not in option_string_indices:
+++ strings = arg_strings[start_index:next_option_string_index]
+++ extras.extend(strings)
+++ start_index = next_option_string_index
+++
+++ # consume the next optional and any arguments for it
+++ start_index = consume_optional(start_index)
+++
+++ # consume any positionals following the last Optional
+++ stop_index = consume_positionals(start_index)
+++
+++ # if we didn't consume all the argument strings, there were extras
+++ extras.extend(arg_strings[stop_index:])
+++
+++ # if we didn't use all the Positional objects, there were too few
+++ # arg strings supplied.
+++ if positionals:
+++ self.error(_('too few arguments'))
+++
+++ # make sure all required actions were present
+++ for action in self._actions:
+++ if action.required:
+++ if action not in seen_actions:
+++ name = _get_action_name(action)
+++ self.error(_('argument %s is required') % name)
+++
+++ # make sure all required groups had one option present
+++ for group in self._mutually_exclusive_groups:
+++ if group.required:
+++ for action in group._group_actions:
+++ if action in seen_non_default_actions:
+++ break
+++
+++ # if no actions were used, report the error
+++ else:
+++ names = [_get_action_name(action)
+++ for action in group._group_actions
+++ if action.help is not SUPPRESS]
+++ msg = _('one of the arguments %s is required')
+++ self.error(msg % ' '.join(names))
+++
+++ # return the updated namespace and the extra arguments
+++ return namespace, extras
+++
+++ def _read_args_from_files(self, arg_strings):
+++ # expand arguments referencing files
+++ new_arg_strings = []
+++ for arg_string in arg_strings:
+++
+++ # for regular arguments, just add them back into the list
+++ if arg_string[0] not in self.fromfile_prefix_chars:
+++ new_arg_strings.append(arg_string)
+++
+++ # replace arguments referencing files with the file content
+++ else:
+++ try:
+++ args_file = open(arg_string[1:])
+++ try:
+++ arg_strings = []
+++ for arg_line in args_file.read().splitlines():
+++ for arg in self.convert_arg_line_to_args(arg_line):
+++ arg_strings.append(arg)
+++ arg_strings = self._read_args_from_files(arg_strings)
+++ new_arg_strings.extend(arg_strings)
+++ finally:
+++ args_file.close()
+++ except IOError:
+++ err = _sys.exc_info()[1]
+++ self.error(str(err))
+++
+++ # return the modified argument list
+++ return new_arg_strings
+++
+++ def convert_arg_line_to_args(self, arg_line):
+++ return [arg_line]
+++
+++ def _match_argument(self, action, arg_strings_pattern):
+++ # match the pattern for this action to the arg strings
+++ nargs_pattern = self._get_nargs_pattern(action)
+++ match = _re.match(nargs_pattern, arg_strings_pattern)
+++
+++ # raise an exception if we weren't able to find a match
+++ if match is None:
+++ nargs_errors = {
+++ None: _('expected one argument'),
+++ OPTIONAL: _('expected at most one argument'),
+++ ONE_OR_MORE: _('expected at least one argument'),
+++ }
+++ default = _('expected %s argument(s)') % action.nargs
+++ msg = nargs_errors.get(action.nargs, default)
+++ raise ArgumentError(action, msg)
+++
+++ # return the number of arguments matched
+++ return len(match.group(1))
+++
+++ def _match_arguments_partial(self, actions, arg_strings_pattern):
+++ # progressively shorten the actions list by slicing off the
+++ # final actions until we find a match
+++ result = []
+++ for i in range(len(actions), 0, -1):
+++ actions_slice = actions[:i]
+++ pattern = ''.join([self._get_nargs_pattern(action)
+++ for action in actions_slice])
+++ match = _re.match(pattern, arg_strings_pattern)
+++ if match is not None:
+++ result.extend([len(string) for string in match.groups()])
+++ break
+++
+++ # return the list of arg string counts
+++ return result
+++
+++ def _parse_optional(self, arg_string):
+++ # if it's an empty string, it was meant to be a positional
+++ if not arg_string:
+++ return None
+++
+++ # if it doesn't start with a prefix, it was meant to be positional
+++ if not arg_string[0] in self.prefix_chars:
+++ return None
+++
+++ # if the option string is present in the parser, return the action
+++ if arg_string in self._option_string_actions:
+++ action = self._option_string_actions[arg_string]
+++ return action, arg_string, None
+++
+++ # if it's just a single character, it was meant to be positional
+++ if len(arg_string) == 1:
+++ return None
+++
+++ # if the option string before the "=" is present, return the action
+++ if '=' in arg_string:
+++ option_string, explicit_arg = arg_string.split('=', 1)
+++ if option_string in self._option_string_actions:
+++ action = self._option_string_actions[option_string]
+++ return action, option_string, explicit_arg
+++
+++ # search through all possible prefixes of the option string
+++ # and all actions in the parser for possible interpretations
+++ option_tuples = self._get_option_tuples(arg_string)
+++
+++ # if multiple actions match, the option string was ambiguous
+++ if len(option_tuples) > 1:
+++ options = ', '.join([option_string
+++ for action, option_string, explicit_arg in option_tuples])
+++ tup = arg_string, options
+++ self.error(_('ambiguous option: %s could match %s') % tup)
+++
+++ # if exactly one action matched, this segmentation is good,
+++ # so return the parsed action
+++ elif len(option_tuples) == 1:
+++ option_tuple, = option_tuples
+++ return option_tuple
+++
+++ # if it was not found as an option, but it looks like a negative
+++ # number, it was meant to be positional
+++ # unless there are negative-number-like options
+++ if self._negative_number_matcher.match(arg_string):
+++ if not self._has_negative_number_optionals:
+++ return None
+++
+++ # if it contains a space, it was meant to be a positional
+++ if ' ' in arg_string:
+++ return None
+++
+++ # it was meant to be an optional but there is no such option
+++ # in this parser (though it might be a valid option in a subparser)
+++ return None, arg_string, None
+++
+++ def _get_option_tuples(self, option_string):
+++ result = []
+++
+++ # option strings starting with two prefix characters are only
+++ # split at the '='
+++ chars = self.prefix_chars
+++ if option_string[0] in chars and option_string[1] in chars:
+++ if '=' in option_string:
+++ option_prefix, explicit_arg = option_string.split('=', 1)
+++ else:
+++ option_prefix = option_string
+++ explicit_arg = None
+++ for option_string in self._option_string_actions:
+++ if option_string.startswith(option_prefix):
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, explicit_arg
+++ result.append(tup)
+++
+++ # single character options can be concatenated with their arguments
+++ # but multiple character options always have to have their argument
+++ # separate
+++ elif option_string[0] in chars and option_string[1] not in chars:
+++ option_prefix = option_string
+++ explicit_arg = None
+++ short_option_prefix = option_string[:2]
+++ short_explicit_arg = option_string[2:]
+++
+++ for option_string in self._option_string_actions:
+++ if option_string == short_option_prefix:
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, short_explicit_arg
+++ result.append(tup)
+++ elif option_string.startswith(option_prefix):
+++ action = self._option_string_actions[option_string]
+++ tup = action, option_string, explicit_arg
+++ result.append(tup)
+++
+++ # shouldn't ever get here
+++ else:
+++ self.error(_('unexpected option string: %s') % option_string)
+++
+++ # return the collected option tuples
+++ return result
+++
+++ def _get_nargs_pattern(self, action):
+++ # in all examples below, we have to allow for '--' args
+++ # which are represented as '-' in the pattern
+++ nargs = action.nargs
+++
+++ # the default (None) is assumed to be a single argument
+++ if nargs is None:
+++ nargs_pattern = '(-*A-*)'
+++
+++ # allow zero or one arguments
+++ elif nargs == OPTIONAL:
+++ nargs_pattern = '(-*A?-*)'
+++
+++ # allow zero or more arguments
+++ elif nargs == ZERO_OR_MORE:
+++ nargs_pattern = '(-*[A-]*)'
+++
+++ # allow one or more arguments
+++ elif nargs == ONE_OR_MORE:
+++ nargs_pattern = '(-*A[A-]*)'
+++
+++ # allow any number of options or arguments
+++ elif nargs == REMAINDER:
+++ nargs_pattern = '([-AO]*)'
+++
+++ # allow one argument followed by any number of options or arguments
+++ elif nargs == PARSER:
+++ nargs_pattern = '(-*A[-AO]*)'
+++
+++ # all others should be integers
+++ else:
+++ nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
+++
+++ # if this is an optional action, -- is not allowed
+++ if action.option_strings:
+++ nargs_pattern = nargs_pattern.replace('-*', '')
+++ nargs_pattern = nargs_pattern.replace('-', '')
+++
+++ # return the pattern
+++ return nargs_pattern
+++
+++ # ========================
+++ # Value conversion methods
+++ # ========================
+++ def _get_values(self, action, arg_strings):
+++ # for everything but PARSER args, strip out '--'
+++ if action.nargs not in [PARSER, REMAINDER]:
+++ arg_strings = [s for s in arg_strings if s != '--']
+++
+++ # optional argument produces a default when not present
+++ if not arg_strings and action.nargs == OPTIONAL:
+++ if action.option_strings:
+++ value = action.const
+++ else:
+++ value = action.default
+++ if isinstance(value, basestring):
+++ value = self._get_value(action, value)
+++ self._check_value(action, value)
+++
+++ # when nargs='*' on a positional, if there were no command-line
+++ # args, use the default if it is anything other than None
+++ elif (not arg_strings and action.nargs == ZERO_OR_MORE and
+++ not action.option_strings):
+++ if action.default is not None:
+++ value = action.default
+++ else:
+++ value = arg_strings
+++ self._check_value(action, value)
+++
+++ # single argument or optional argument produces a single value
+++ elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
+++ arg_string, = arg_strings
+++ value = self._get_value(action, arg_string)
+++ self._check_value(action, value)
+++
+++ # REMAINDER arguments convert all values, checking none
+++ elif action.nargs == REMAINDER:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++
+++ # PARSER arguments convert all values, but check only the first
+++ elif action.nargs == PARSER:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++ self._check_value(action, value[0])
+++
+++ # all other types of nargs produce a list
+++ else:
+++ value = [self._get_value(action, v) for v in arg_strings]
+++ for v in value:
+++ self._check_value(action, v)
+++
+++ # return the converted value
+++ return value
+++
+++ def _get_value(self, action, arg_string):
+++ type_func = self._registry_get('type', action.type, action.type)
+++ if not _callable(type_func):
+++ msg = _('%r is not callable')
+++ raise ArgumentError(action, msg % type_func)
+++
+++ # convert the value to the appropriate type
+++ try:
+++ result = type_func(arg_string)
+++
+++ # ArgumentTypeErrors indicate errors
+++ except ArgumentTypeError:
+++ name = getattr(action.type, '__name__', repr(action.type))
+++ msg = str(_sys.exc_info()[1])
+++ raise ArgumentError(action, msg)
+++
+++ # TypeErrors or ValueErrors also indicate errors
+++ except (TypeError, ValueError):
+++ name = getattr(action.type, '__name__', repr(action.type))
+++ msg = _('invalid %s value: %r')
+++ raise ArgumentError(action, msg % (name, arg_string))
+++
+++ # return the converted value
+++ return result
+++
+++ def _check_value(self, action, value):
+++ # converted value must be one of the choices (if specified)
+++ if action.choices is not None and value not in action.choices:
+++ tup = value, ', '.join(map(repr, action.choices))
+++ msg = _('invalid choice: %r (choose from %s)') % tup
+++ raise ArgumentError(action, msg)
+++
+++ # =======================
+++ # Help-formatting methods
+++ # =======================
+++ def format_usage(self):
+++ formatter = self._get_formatter()
+++ formatter.add_usage(self.usage, self._actions,
+++ self._mutually_exclusive_groups)
+++ return formatter.format_help()
+++
+++ def format_help(self):
+++ formatter = self._get_formatter()
+++
+++ # usage
+++ formatter.add_usage(self.usage, self._actions,
+++ self._mutually_exclusive_groups)
+++
+++ # description
+++ formatter.add_text(self.description)
+++
+++ # positionals, optionals and user-defined groups
+++ for action_group in self._action_groups:
+++ formatter.start_section(action_group.title)
+++ formatter.add_text(action_group.description)
+++ formatter.add_arguments(action_group._group_actions)
+++ formatter.end_section()
+++
+++ # epilog
+++ formatter.add_text(self.epilog)
+++
+++ # determine help from format above
+++ return formatter.format_help()
+++
+++ def format_version(self):
+++ import warnings
+++ warnings.warn(
+++ 'The format_version method is deprecated -- the "version" '
+++ 'argument to ArgumentParser is no longer supported.',
+++ DeprecationWarning)
+++ formatter = self._get_formatter()
+++ formatter.add_text(self.version)
+++ return formatter.format_help()
+++
+++ def _get_formatter(self):
+++ return self.formatter_class(prog=self.prog)
+++
+++ # =====================
+++ # Help-printing methods
+++ # =====================
+++ def print_usage(self, file=None):
+++ if file is None:
+++ file = _sys.stdout
+++ self._print_message(self.format_usage(), file)
+++
+++ def print_help(self, file=None):
+++ if file is None:
+++ file = _sys.stdout
+++ self._print_message(self.format_help(), file)
+++
+++ def print_version(self, file=None):
+++ import warnings
+++ warnings.warn(
+++ 'The print_version method is deprecated -- the "version" '
+++ 'argument to ArgumentParser is no longer supported.',
+++ DeprecationWarning)
+++ self._print_message(self.format_version(), file)
+++
+++ def _print_message(self, message, file=None):
+++ if message:
+++ if file is None:
+++ file = _sys.stderr
+++ file.write(message)
+++
+++ # ===============
+++ # Exiting methods
+++ # ===============
+++ def exit(self, status=0, message=None):
+++ if message:
+++ self._print_message(message, _sys.stderr)
+++ _sys.exit(status)
+++
+++ def error(self, message):
+++ """error(message: string)
+++
+++ Prints a usage message incorporating the message to stderr and
+++ exits.
+++
+++ If you override this in a subclass, it should not return -- it
+++ should either exit or raise an exception.
+++ """
+++ self.print_usage(_sys.stderr)
+++ self.exit(2, _('%s: error: %s\n') % (self.prog, message))
++diff -up mozilla-aurora/rebase/contextdecorator.py.rebase-dir mozilla-aurora/rebase/contextdecorator.py
++--- mozilla-aurora/rebase/contextdecorator.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/contextdecorator.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,185 @@
+++# Copyright (C) 2007-2010 Michael Foord
+++# E-mail: michael AT voidspace DOT org DOT uk
+++# http://pypi.python.org/pypi/contextdecorator
+++'''
+++Create objects that act as both context managers *and* as decorators, and behave
+++the same in both cases.
+++
+++Context managers inheriting from ``ContextDecorator`` have to implement
+++``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional
+++exception handling even when used as a decorator.
+++
+++Example::
+++
+++ from contextlib import ContextDecorator
+++
+++ class mycontext(ContextDecorator):
+++ def __enter__(self):
+++ print 'Starting'
+++ return self
+++
+++ def __exit__(self, *exc):
+++ print 'Finishing'
+++ return False
+++
+++ @mycontext()
+++ def function():
+++ print 'The bit in the middle'
+++
+++ with mycontext():
+++ print 'The bit in the middle'
+++
+++Existing context managers that already have a base class can be extended by
+++using ``ContextDecorator`` as a mixin class::
+++
+++ from contextlib import ContextDecorator
+++
+++ class mycontext(ContextBaseClass, ContextDecorator):
+++ def __enter__(self):
+++ return self
+++
+++ def __exit__(self, *exc):
+++ return False
+++
+++'''
+++
+++import sys
+++
+++try:
+++ from functools import wraps
+++except ImportError:
+++ # Python 2.4 compatibility
+++ def wraps(original):
+++ def inner(f):
+++ f.__name__ = original.__name__
+++ return f
+++ return inner
+++
+++# horrible reraise code for compatibility
+++# with Python 2 & 3
+++if sys.version_info >= (3,0):
+++ exec ("""
+++def _reraise(cls, val, tb):
+++ raise val
+++""")
+++else:
+++ exec ("""
+++def _reraise(cls, val, tb):
+++ raise cls, val, tb
+++""")
+++
+++try:
+++ next
+++except NameError:
+++ # Python 2.4 / 2.5
+++ def next(gen):
+++ return gen.next()
+++
+++__all__ = ['__version__', 'ContextDecorator', 'contextmanager']
+++
+++__version__ = '0.10.0'
+++
+++
+++_NO_EXCEPTION = (None, None, None)
+++
+++class ContextDecorator(object):
+++ "A base class or mixin that enables context managers to work as decorators."
+++
+++ def __call__(self, f):
+++ @wraps(f)
+++ def inner(*args, **kw):
+++ self.__enter__()
+++
+++ exc = _NO_EXCEPTION
+++ try:
+++ result = f(*args, **kw)
+++ except Exception:
+++ exc = sys.exc_info()
+++
+++ catch = self.__exit__(*exc)
+++
+++ if not catch and exc is not _NO_EXCEPTION:
+++ _reraise(*exc)
+++ return result
+++ return inner
+++
+++
+++
+++class GeneratorContextManager(ContextDecorator):
+++ """Helper for @contextmanager decorator."""
+++
+++ def __init__(self, gen):
+++ self.gen = gen
+++
+++ def __enter__(self):
+++ try:
+++ return next(self.gen)
+++ except StopIteration:
+++ raise RuntimeError("generator didn't yield")
+++
+++ def __exit__(self, type, value, traceback):
+++ if type is None:
+++ try:
+++ next(self.gen)
+++ except StopIteration:
+++ return
+++ else:
+++ raise RuntimeError("generator didn't stop")
+++ else:
+++ if value is None:
+++ # Need to force instantiation so we can reliably
+++ # tell if we get the same exception back
+++ value = type()
+++ try:
+++ self.gen.throw(type, value, traceback)
+++ raise RuntimeError("generator didn't stop after throw()")
+++ except StopIteration:
+++ # Suppress the exception *unless* it's the same exception that
+++ # was passed to throw(). This prevents a StopIteration
+++ # raised inside the "with" statement from being suppressed
+++ exc = sys.exc_info()[1]
+++ return exc is not value
+++ except:
+++ # only re-raise if it's *not* the exception that was
+++ # passed to throw(), because __exit__() must not raise
+++ # an exception unless __exit__() itself failed. But throw()
+++ # has to raise the exception to signal propagation, so this
+++ # fixes the impedance mismatch between the throw() protocol
+++ # and the __exit__() protocol.
+++ #
+++ if sys.exc_info()[1] is not value:
+++ raise
+++
+++
+++def contextmanager(func):
+++ """@contextmanager decorator.
+++
+++ Typical usage:
+++
+++ @contextmanager
+++ def some_generator(<arguments>):
+++ <setup>
+++ try:
+++ yield <value>
+++ finally:
+++ <cleanup>
+++
+++ This makes this:
+++
+++ with some_generator(<arguments>) as <variable>:
+++ <body>
+++
+++ equivalent to this:
+++
+++ <setup>
+++ try:
+++ <variable> = <value>
+++ <body>
+++ finally:
+++ <cleanup>
+++
+++ """
+++ @wraps(func)
+++ def helper(*args, **kwds):
+++ return GeneratorContextManager(func(*args, **kwds))
+++ return helper
++\ No newline at end of file
++diff -up mozilla-aurora/rebase/Counter.py.rebase-dir mozilla-aurora/rebase/Counter.py
++--- mozilla-aurora/rebase/Counter.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/Counter.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,189 @@
+++from operator import itemgetter
+++from heapq import nlargest
+++from itertools import repeat, ifilter
+++
+++class Counter(dict):
+++ '''Dict subclass for counting hashable objects. Sometimes called a bag
+++ or multiset. Elements are stored as dictionary keys and their counts
+++ are stored as dictionary values.
+++
+++ >>> Counter('zyzygy')
+++ Counter({'y': 3, 'z': 2, 'g': 1})
+++
+++ '''
+++
+++ def __init__(self, iterable=None, **kwds):
+++ '''Create a new, empty Counter object. And if given, count elements
+++ from an input iterable. Or, initialize the count from another mapping
+++ of elements to their counts.
+++
+++ >>> c = Counter() # a new, empty counter
+++ >>> c = Counter('gallahad') # a new counter from an iterable
+++ >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
+++ >>> c = Counter(a=4, b=2) # a new counter from keyword args
+++
+++ '''
+++ self.update(iterable, **kwds)
+++
+++ def __missing__(self, key):
+++ return 0
+++
+++ def most_common(self, n=None):
+++ '''List the n most common elements and their counts from the most
+++ common to the least. If n is None, then list all element counts.
+++
+++ >>> Counter('abracadabra').most_common(3)
+++ [('a', 5), ('r', 2), ('b', 2)]
+++
+++ '''
+++ if n is None:
+++ return sorted(self.iteritems(), key=itemgetter(1), reverse=True)
+++ return nlargest(n, self.iteritems(), key=itemgetter(1))
+++
+++ def elements(self):
+++ '''Iterator over elements repeating each as many times as its count.
+++
+++ >>> c = Counter('ABCABC')
+++ >>> sorted(c.elements())
+++ ['A', 'A', 'B', 'B', 'C', 'C']
+++
+++ If an element's count has been set to zero or is a negative number,
+++ elements() will ignore it.
+++
+++ '''
+++ for elem, count in self.iteritems():
+++ for _ in repeat(None, count):
+++ yield elem
+++
+++ # Override dict methods where the meaning changes for Counter objects.
+++
+++ @classmethod
+++ def fromkeys(cls, iterable, v=None):
+++ raise NotImplementedError(
+++ 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
+++
+++ def update(self, iterable=None, **kwds):
+++ '''Like dict.update() but add counts instead of replacing them.
+++
+++ Source can be an iterable, a dictionary, or another Counter instance.
+++
+++ >>> c = Counter('which')
+++ >>> c.update('witch') # add elements from another iterable
+++ >>> d = Counter('watch')
+++ >>> c.update(d) # add elements from another counter
+++ >>> c['h'] # four 'h' in which, witch, and watch
+++ 4
+++
+++ '''
+++ if iterable is not None:
+++ if hasattr(iterable, 'iteritems'):
+++ if self:
+++ self_get = self.get
+++ for elem, count in iterable.iteritems():
+++ self[elem] = self_get(elem, 0) + count
+++ else:
+++ dict.update(self, iterable) # fast path when counter is empty
+++ else:
+++ self_get = self.get
+++ for elem in iterable:
+++ self[elem] = self_get(elem, 0) + 1
+++ if kwds:
+++ self.update(kwds)
+++
+++ def copy(self):
+++ 'Like dict.copy() but returns a Counter instance instead of a dict.'
+++ return Counter(self)
+++
+++ def __delitem__(self, elem):
+++ 'Like dict.__delitem__() but does not raise KeyError for missing values.'
+++ if elem in self:
+++ dict.__delitem__(self, elem)
+++
+++ def __repr__(self):
+++ if not self:
+++ return '%s()' % self.__class__.__name__
+++ items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
+++ return '%s({%s})' % (self.__class__.__name__, items)
+++
+++ # Multiset-style mathematical operations discussed in:
+++ # Knuth TAOCP Volume II section 4.6.3 exercise 19
+++ # and at http://en.wikipedia.org/wiki/Multiset
+++ #
+++ # Outputs guaranteed to only include positive counts.
+++ #
+++ # To strip negative and zero counts, add-in an empty counter:
+++ # c += Counter()
+++
+++ def __add__(self, other):
+++ '''Add counts from two counters.
+++
+++ >>> Counter('abbb') + Counter('bcc')
+++ Counter({'b': 4, 'c': 2, 'a': 1})
+++
+++
+++ '''
+++ if not isinstance(other, Counter):
+++ return NotImplemented
+++ result = Counter()
+++ for elem in set(self) | set(other):
+++ newcount = self[elem] + other[elem]
+++ if newcount > 0:
+++ result[elem] = newcount
+++ return result
+++
+++ def __sub__(self, other):
+++ ''' Subtract count, but keep only results with positive counts.
+++
+++ >>> Counter('abbbc') - Counter('bccd')
+++ Counter({'b': 2, 'a': 1})
+++
+++ '''
+++ if not isinstance(other, Counter):
+++ return NotImplemented
+++ result = Counter()
+++ for elem in set(self) | set(other):
+++ newcount = self[elem] - other[elem]
+++ if newcount > 0:
+++ result[elem] = newcount
+++ return result
+++
+++ def __or__(self, other):
+++ '''Union is the maximum of value in either of the input counters.
+++
+++ >>> Counter('abbb') | Counter('bcc')
+++ Counter({'b': 3, 'c': 2, 'a': 1})
+++
+++ '''
+++ if not isinstance(other, Counter):
+++ return NotImplemented
+++ _max = max
+++ result = Counter()
+++ for elem in set(self) | set(other):
+++ newcount = _max(self[elem], other[elem])
+++ if newcount > 0:
+++ result[elem] = newcount
+++ return result
+++
+++ def __and__(self, other):
+++ ''' Intersection is the minimum of corresponding counts.
+++
+++ >>> Counter('abbb') & Counter('bcc')
+++ Counter({'b': 1})
+++
+++ '''
+++ if not isinstance(other, Counter):
+++ return NotImplemented
+++ _min = min
+++ result = Counter()
+++ if len(self) < len(other):
+++ self, other = other, self
+++ for elem in ifilter(self.__contains__, other):
+++ newcount = _min(self[elem], other[elem])
+++ if newcount > 0:
+++ result[elem] = newcount
+++ return result
+++
+++
+++if __name__ == '__main__':
+++ import doctest
+++ print doctest.testmod()
++diff -up mozilla-aurora/rebase/mycollections.py.rebase-dir mozilla-aurora/rebase/mycollections.py
++--- mozilla-aurora/rebase/mycollections.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/mycollections.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,38 @@
+++from ordereddict import OrderedDict
+++from namedtuple import namedtuple
+++
+++class defaultdict(dict):
+++ def __init__(self, default_factory=None, *a, **kw):
+++ if (default_factory is not None and
+++ not hasattr(default_factory, '__call__')):
+++ raise TypeError('first argument must be callable')
+++ dict.__init__(self, *a, **kw)
+++ self.default_factory = default_factory
+++ def __getitem__(self, key):
+++ try:
+++ return dict.__getitem__(self, key)
+++ except KeyError:
+++ return self.__missing__(key)
+++ def __missing__(self, key):
+++ if self.default_factory is None:
+++ raise KeyError(key)
+++ self[key] = value = self.default_factory()
+++ return value
+++ def __reduce__(self):
+++ if self.default_factory is None:
+++ args = tuple()
+++ else:
+++ args = self.default_factory,
+++ return type(self), args, None, None, self.items()
+++ def copy(self):
+++ return self.__copy__()
+++ def __copy__(self):
+++ return type(self)(self.default_factory, self)
+++ def __deepcopy__(self, memo):
+++ import copy
+++ return type(self)(self.default_factory,
+++ copy.deepcopy(self.items()))
+++ def __repr__(self):
+++ return 'defaultdict(%s, %s)' % (self.default_factory,
+++ dict.__repr__(self))
+++
++diff -up mozilla-aurora/rebase/mypickle.py.rebase-dir mozilla-aurora/rebase/mypickle.py
++--- mozilla-aurora/rebase/mypickle.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/mypickle.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,1403 @@
+++"""Create portable serialized representations of Python objects.
+++
+++See module cPickle for a (much) faster implementation.
+++See module copy_reg for a mechanism for registering custom picklers.
+++See module pickletools source for extensive comments.
+++
+++Classes:
+++
+++ Pickler
+++ Unpickler
+++
+++Functions:
+++
+++ dump(object, file)
+++ dumps(object) -> string
+++ load(file) -> object
+++ loads(string) -> object
+++
+++Misc variables:
+++
+++ __version__
+++ format_version
+++ compatible_formats
+++
+++"""
+++
+++__version__ = "$Revision: 72223 $" # Code version
+++
+++from types import *
+++from copy_reg import dispatch_table
+++from copy_reg import _extension_registry, _inverted_registry, _extension_cache
+++import marshal
+++import sys
+++import struct
+++import re
+++
+++__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
+++ "Unpickler", "dump", "dumps", "load", "loads"]
+++
+++# These are purely informational; no code uses these.
+++format_version = "2.0" # File format version we write
+++compatible_formats = ["1.0", # Original protocol 0
+++ "1.1", # Protocol 0 with INST added
+++ "1.2", # Original protocol 1
+++ "1.3", # Protocol 1 with BINFLOAT added
+++ "2.0", # Protocol 2
+++ ] # Old format versions we can read
+++
+++# Keep in synch with cPickle. This is the highest protocol number we
+++# know how to read.
+++HIGHEST_PROTOCOL = 2
+++
+++# Why use struct.pack() for pickling but marshal.loads() for
+++# unpickling? struct.pack() is 40% faster than marshal.dumps(), but
+++# marshal.loads() is twice as fast as struct.unpack()!
+++mloads = marshal.loads
+++
+++class PickleError(Exception):
+++ """A common base class for the other pickling exceptions."""
+++ pass
+++
+++class PicklingError(PickleError):
+++ """This exception is raised when an unpicklable object is passed to the
+++ dump() method.
+++
+++ """
+++ pass
+++
+++class UnpicklingError(PickleError):
+++ """This exception is raised when there is a problem unpickling an object,
+++ such as a security violation.
+++
+++ Note that other exceptions may also be raised during unpickling, including
+++ (but not necessarily limited to) AttributeError, EOFError, ImportError,
+++ and IndexError.
+++
+++ """
+++ pass
+++
+++# An instance of _Stop is raised by Unpickler.load_stop() in response to
+++# the STOP opcode, passing the object that is the result of unpickling.
+++class _Stop(Exception):
+++ def __init__(self, value):
+++ self.value = value
+++
+++# Jython has PyStringMap; it's a dict subclass with string keys
+++try:
+++ from org.python.core import PyStringMap
+++except ImportError:
+++ PyStringMap = None
+++
+++# UnicodeType may or may not be exported (normally imported from types)
+++try:
+++ UnicodeType
+++except NameError:
+++ UnicodeType = None
+++
+++# Pickle opcodes. See pickletools.py for extensive docs. The listing
+++# here is in kind-of alphabetical order of 1-character pickle code.
+++# pickletools groups them by purpose.
+++
+++MARK = '(' # push special markobject on stack
+++STOP = '.' # every pickle ends with STOP
+++POP = '0' # discard topmost stack item
+++POP_MARK = '1' # discard stack top through topmost markobject
+++DUP = '2' # duplicate top stack item
+++FLOAT = 'F' # push float object; decimal string argument
+++INT = 'I' # push integer or bool; decimal string argument
+++BININT = 'J' # push four-byte signed int
+++BININT1 = 'K' # push 1-byte unsigned int
+++LONG = 'L' # push long; decimal string argument
+++BININT2 = 'M' # push 2-byte unsigned int
+++NONE = 'N' # push None
+++PERSID = 'P' # push persistent object; id is taken from string arg
+++BINPERSID = 'Q' # " " " ; " " " " stack
+++REDUCE = 'R' # apply callable to argtuple, both on stack
+++STRING = 'S' # push string; NL-terminated string argument
+++BINSTRING = 'T' # push string; counted binary string argument
+++SHORT_BINSTRING = 'U' # " " ; " " " " < 256 bytes
+++UNICODE = 'V' # push Unicode string; raw-unicode-escaped'd argument
+++BINUNICODE = 'X' # " " " ; counted UTF-8 string argument
+++APPEND = 'a' # append stack top to list below it
+++BUILD = 'b' # call __setstate__ or __dict__.update()
+++GLOBAL = 'c' # push self.find_class(modname, name); 2 string args
+++DICT = 'd' # build a dict from stack items
+++EMPTY_DICT = '}' # push empty dict
+++APPENDS = 'e' # extend list on stack by topmost stack slice
+++GET = 'g' # push item from memo on stack; index is string arg
+++BINGET = 'h' # " " " " " " ; " " 1-byte arg
+++INST = 'i' # build & push class instance
+++LONG_BINGET = 'j' # push item from memo on stack; index is 4-byte arg
+++LIST = 'l' # build list from topmost stack items
+++EMPTY_LIST = ']' # push empty list
+++OBJ = 'o' # build & push class instance
+++PUT = 'p' # store stack top in memo; index is string arg
+++BINPUT = 'q' # " " " " " ; " " 1-byte arg
+++LONG_BINPUT = 'r' # " " " " " ; " " 4-byte arg
+++SETITEM = 's' # add key+value pair to dict
+++TUPLE = 't' # build tuple from topmost stack items
+++EMPTY_TUPLE = ')' # push empty tuple
+++SETITEMS = 'u' # modify dict by adding topmost key+value pairs
+++BINFLOAT = 'G' # push float; arg is 8-byte float encoding
+++
+++TRUE = 'I01\n' # not an opcode; see INT docs in pickletools.py
+++FALSE = 'I00\n' # not an opcode; see INT docs in pickletools.py
+++
+++# Protocol 2
+++
+++PROTO = '\x80' # identify pickle protocol
+++NEWOBJ = '\x81' # build object by applying cls.__new__ to argtuple
+++EXT1 = '\x82' # push object from extension registry; 1-byte index
+++EXT2 = '\x83' # ditto, but 2-byte index
+++EXT4 = '\x84' # ditto, but 4-byte index
+++TUPLE1 = '\x85' # build 1-tuple from stack top
+++TUPLE2 = '\x86' # build 2-tuple from two topmost stack items
+++TUPLE3 = '\x87' # build 3-tuple from three topmost stack items
+++NEWTRUE = '\x88' # push True
+++NEWFALSE = '\x89' # push False
+++LONG1 = '\x8a' # push long from < 256 bytes
+++LONG4 = '\x8b' # push really big long
+++
+++_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3]
+++
+++
+++__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)])
+++del x
+++
+++
+++# Pickling machinery
+++
+++class Pickler:
+++
+++ def __init__(self, file, protocol=None):
+++ """This takes a file-like object for writing a pickle data stream.
+++
+++ The optional protocol argument tells the pickler to use the
+++ given protocol; supported protocols are 0, 1, 2. The default
+++ protocol is 0, to be backwards compatible. (Protocol 0 is the
+++ only protocol that can be written to a file opened in text
+++ mode and read back successfully. When using a protocol higher
+++ than 0, make sure the file is opened in binary mode, both when
+++ pickling and unpickling.)
+++
+++ Protocol 1 is more efficient than protocol 0; protocol 2 is
+++ more efficient than protocol 1.
+++
+++ Specifying a negative protocol version selects the highest
+++ protocol version supported. The higher the protocol used, the
+++ more recent the version of Python needed to read the pickle
+++ produced.
+++
+++ The file parameter must have a write() method that accepts a single
+++ string argument. It can thus be an open file object, a StringIO
+++ object, or any other custom object that meets this interface.
+++
+++ """
+++ if protocol is None:
+++ protocol = 0
+++ if protocol < 0:
+++ protocol = HIGHEST_PROTOCOL
+++ elif not 0 <= protocol <= HIGHEST_PROTOCOL:
+++ raise ValueError("pickle protocol must be <= %d" % HIGHEST_PROTOCOL)
+++ self.write = file.write
+++ self.memo = {}
+++ self.proto = int(protocol)
+++ self.bin = protocol >= 1
+++ self.fast = 0
+++
+++ def clear_memo(self):
+++ """Clears the pickler's "memo".
+++
+++ The memo is the data structure that remembers which objects the
+++ pickler has already seen, so that shared or recursive objects are
+++ pickled by reference and not by value. This method is useful when
+++ re-using picklers.
+++
+++ """
+++ self.memo.clear()
+++
+++ def dump(self, obj):
+++ """Write a pickled representation of obj to the open file."""
+++ if self.proto >= 2:
+++ self.write(PROTO + chr(self.proto))
+++ self.save(obj)
+++ self.write(STOP)
+++
+++ def memoize(self, obj):
+++ """Store an object in the memo."""
+++
+++ # The Pickler memo is a dictionary mapping object ids to 2-tuples
+++ # that contain the Unpickler memo key and the object being memoized.
+++ # The memo key is written to the pickle and will become
+++ # the key in the Unpickler's memo. The object is stored in the
+++ # Pickler memo so that transient objects are kept alive during
+++ # pickling.
+++
+++ # The use of the Unpickler memo length as the memo key is just a
+++ # convention. The only requirement is that the memo values be unique.
+++ # But there appears no advantage to any other scheme, and this
+++ # scheme allows the Unpickler memo to be implemented as a plain (but
+++ # growable) array, indexed by memo key.
+++ if self.fast:
+++ return
+++ assert id(obj) not in self.memo
+++ memo_len = len(self.memo)
+++ self.write(self.put(memo_len))
+++ self.memo[id(obj)] = memo_len, obj
+++
+++ # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
+++ def put(self, i, pack=struct.pack):
+++ if self.bin:
+++ if i < 256:
+++ return BINPUT + chr(i)
+++ else:
+++ return LONG_BINPUT + pack("<i", i)
+++
+++ return PUT + repr(i) + '\n'
+++
+++ # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
+++ def get(self, i, pack=struct.pack):
+++ if self.bin:
+++ if i < 256:
+++ return BINGET + chr(i)
+++ else:
+++ return LONG_BINGET + pack("<i", i)
+++
+++ return GET + repr(i) + '\n'
+++
+++ def save(self, obj):
+++ # Check for persistent id (defined by a subclass)
+++ pid = self.persistent_id(obj)
+++ if pid:
+++ self.save_pers(pid)
+++ return
+++
+++ # Check the memo
+++ x = self.memo.get(id(obj))
+++ if x:
+++ self.write(self.get(x[0]))
+++ return
+++
+++ # Check the type dispatch table
+++ t = type(obj)
+++ f = self.dispatch.get(t)
+++ if f:
+++ f(self, obj) # Call unbound method with explicit self
+++ return
+++
+++ # Check copy_reg.dispatch_table
+++ reduce = dispatch_table.get(t)
+++ if reduce:
+++ rv = reduce(obj)
+++ else:
+++ # Check for a class with a custom metaclass; treat as regular class
+++ try:
+++ issc = issubclass(t, TypeType)
+++ except TypeError: # t is not a class (old Boost; see SF #502085)
+++ issc = 0
+++ if issc:
+++ self.save_global(obj)
+++ return
+++
+++ # Check for a __reduce_ex__ method, fall back to __reduce__
+++ reduce = getattr(obj, "__reduce_ex__", None)
+++ if reduce:
+++ rv = reduce(self.proto)
+++ else:
+++ reduce = getattr(obj, "__reduce__", None)
+++ if reduce:
+++ rv = reduce()
+++ else:
+++ raise PicklingError("Can't pickle %r object: %r" %
+++ (t.__name__, obj))
+++
+++ # Check for string returned by reduce(), meaning "save as global"
+++ if type(rv) is StringType:
+++ self.save_global(obj, rv)
+++ return
+++
+++ # Assert that reduce() returned a tuple
+++ if type(rv) is not TupleType:
+++ raise PicklingError("%s must return string or tuple" % reduce)
+++
+++ # Assert that it returned an appropriately sized tuple
+++ l = len(rv)
+++ if not (2 <= l <= 5):
+++ raise PicklingError("Tuple returned by %s must have "
+++ "two to five elements" % reduce)
+++
+++ # Save the reduce() output and finally memoize the object
+++ self.save_reduce(obj=obj, *rv)
+++
+++ def persistent_id(self, obj):
+++ # This exists so a subclass can override it
+++ return None
+++
+++ def save_pers(self, pid):
+++ # Save a persistent id reference
+++ if self.bin:
+++ self.save(pid)
+++ self.write(BINPERSID)
+++ else:
+++ self.write(PERSID + str(pid) + '\n')
+++
+++ def save_reduce(self, func, args, state=None,
+++ listitems=None, dictitems=None, obj=None):
+++ # This API is called by some subclasses
+++
+++ # Assert that args is a tuple or None
+++ if not isinstance(args, TupleType):
+++ raise PicklingError("args from reduce() should be a tuple")
+++
+++ # Assert that func is callable
+++ if not hasattr(func, '__call__'):
+++ raise PicklingError("func from reduce should be callable")
+++
+++ save = self.save
+++ write = self.write
+++
+++ # Protocol 2 special case: if func's name is __newobj__, use NEWOBJ
+++ if self.proto >= 2 and getattr(func, "__name__", "") == "__newobj__":
+++ # A __reduce__ implementation can direct protocol 2 to
+++ # use the more efficient NEWOBJ opcode, while still
+++ # allowing protocol 0 and 1 to work normally. For this to
+++ # work, the function returned by __reduce__ should be
+++ # called __newobj__, and its first argument should be a
+++ # new-style class. The implementation for __newobj__
+++ # should be as follows, although pickle has no way to
+++ # verify this:
+++ #
+++ # def __newobj__(cls, *args):
+++ # return cls.__new__(cls, *args)
+++ #
+++ # Protocols 0 and 1 will pickle a reference to __newobj__,
+++ # while protocol 2 (and above) will pickle a reference to
+++ # cls, the remaining args tuple, and the NEWOBJ code,
+++ # which calls cls.__new__(cls, *args) at unpickling time
+++ # (see load_newobj below). If __reduce__ returns a
+++ # three-tuple, the state from the third tuple item will be
+++ # pickled regardless of the protocol, calling __setstate__
+++ # at unpickling time (see load_build below).
+++ #
+++ # Note that no standard __newobj__ implementation exists;
+++ # you have to provide your own. This is to enforce
+++ # compatibility with Python 2.2 (pickles written using
+++ # protocol 0 or 1 in Python 2.3 should be unpicklable by
+++ # Python 2.2).
+++ cls = args[0]
+++ if not hasattr(cls, "__new__"):
+++ raise PicklingError(
+++ "args[0] from __newobj__ args has no __new__")
+++ if obj is not None and cls is not obj.__class__:
+++ raise PicklingError(
+++ "args[0] from __newobj__ args has the wrong class")
+++ args = args[1:]
+++ save(cls)
+++ save(args)
+++ write(NEWOBJ)
+++ else:
+++ save(func)
+++ save(args)
+++ write(REDUCE)
+++
+++ if obj is not None:
+++ self.memoize(obj)
+++
+++ # More new special cases (that work with older protocols as
+++ # well): when __reduce__ returns a tuple with 4 or 5 items,
+++ # the 4th and 5th item should be iterators that provide list
+++ # items and dict items (as (key, value) tuples), or None.
+++
+++ if listitems is not None:
+++ self._batch_appends(listitems)
+++
+++ if dictitems is not None:
+++ self._batch_setitems(dictitems)
+++
+++ if state is not None:
+++ save(state)
+++ write(BUILD)
+++
+++ # Methods below this point are dispatched through the dispatch table
+++
+++ dispatch = {}
+++
+++ def save_none(self, obj):
+++ self.write(NONE)
+++ dispatch[NoneType] = save_none
+++
+++ def save_bool(self, obj):
+++ if self.proto >= 2:
+++ self.write(obj and NEWTRUE or NEWFALSE)
+++ else:
+++ self.write(obj and TRUE or FALSE)
+++ dispatch[bool] = save_bool
+++
+++ def save_int(self, obj, pack=struct.pack):
+++ if self.bin:
+++ # If the int is small enough to fit in a signed 4-byte 2's-comp
+++ # format, we can store it more efficiently than the general
+++ # case.
+++ # First one- and two-byte unsigned ints:
+++ if obj >= 0:
+++ if obj <= 0xff:
+++ self.write(BININT1 + chr(obj))
+++ return
+++ if obj <= 0xffff:
+++ self.write("%c%c%c" % (BININT2, obj&0xff, obj>>8))
+++ return
+++ # Next check for 4-byte signed ints:
+++ high_bits = obj >> 31 # note that Python shift sign-extends
+++ if high_bits == 0 or high_bits == -1:
+++ # All high bits are copies of bit 2**31, so the value
+++ # fits in a 4-byte signed int.
+++ self.write(BININT + pack("<i", obj))
+++ return
+++ # Text pickle, or int too big to fit in signed 4-byte format.
+++ self.write(INT + repr(obj) + '\n')
+++ dispatch[IntType] = save_int
+++
+++ def save_long(self, obj, pack=struct.pack):
+++ if self.proto >= 2:
+++ bytes = encode_long(obj)
+++ n = len(bytes)
+++ if n < 256:
+++ self.write(LONG1 + chr(n) + bytes)
+++ else:
+++ self.write(LONG4 + pack("<i", n) + bytes)
+++ return
+++ self.write(LONG + repr(obj) + '\n')
+++ dispatch[LongType] = save_long
+++
+++ def save_float(self, obj, pack=struct.pack):
+++ print obj
+++ if obj == float('inf'):
+++ self.write(FLOAT + repr(float('9999999999999.0')) + '\n')
+++ else:
+++ if obj == float('-inf'):
+++ self.write(FLOAT + repr(float('-9999999999999.0')) + '\n')
+++ else:
+++ if self.bin:
+++ self.write(BINFLOAT + pack('>d', obj))
+++ else:
+++ self.write(FLOAT + repr(obj) + '\n')
+++ dispatch[FloatType] = save_float
+++
+++ def save_string(self, obj, pack=struct.pack):
+++ if self.bin:
+++ n = len(obj)
+++ if n < 256:
+++ self.write(SHORT_BINSTRING + chr(n) + obj)
+++ else:
+++ self.write(BINSTRING + pack("<i", n) + obj)
+++ else:
+++ self.write(STRING + repr(obj) + '\n')
+++ self.memoize(obj)
+++ dispatch[StringType] = save_string
+++
+++ def save_unicode(self, obj, pack=struct.pack):
+++ if self.bin:
+++ encoding = obj.encode('utf-8')
+++ n = len(encoding)
+++ self.write(BINUNICODE + pack("<i", n) + encoding)
+++ else:
+++ obj = obj.replace("\\", "\\u005c")
+++ obj = obj.replace("\n", "\\u000a")
+++ self.write(UNICODE + obj.encode('raw-unicode-escape') + '\n')
+++ self.memoize(obj)
+++ dispatch[UnicodeType] = save_unicode
+++
+++ if StringType is UnicodeType:
+++ # This is true for Jython
+++ def save_string(self, obj, pack=struct.pack):
+++ unicode = obj.isunicode()
+++
+++ if self.bin:
+++ if unicode:
+++ obj = obj.encode("utf-8")
+++ l = len(obj)
+++ if l < 256 and not unicode:
+++ self.write(SHORT_BINSTRING + chr(l) + obj)
+++ else:
+++ s = pack("<i", l)
+++ if unicode:
+++ self.write(BINUNICODE + s + obj)
+++ else:
+++ self.write(BINSTRING + s + obj)
+++ else:
+++ if unicode:
+++ obj = obj.replace("\\", "\\u005c")
+++ obj = obj.replace("\n", "\\u000a")
+++ obj = obj.encode('raw-unicode-escape')
+++ self.write(UNICODE + obj + '\n')
+++ else:
+++ self.write(STRING + repr(obj) + '\n')
+++ self.memoize(obj)
+++ dispatch[StringType] = save_string
+++
+++ def save_tuple(self, obj):
+++ write = self.write
+++ proto = self.proto
+++
+++ n = len(obj)
+++ if n == 0:
+++ if proto:
+++ write(EMPTY_TUPLE)
+++ else:
+++ write(MARK + TUPLE)
+++ return
+++
+++ save = self.save
+++ memo = self.memo
+++ if n <= 3 and proto >= 2:
+++ for element in obj:
+++ save(element)
+++ # Subtle. Same as in the big comment below.
+++ if id(obj) in memo:
+++ get = self.get(memo[id(obj)][0])
+++ write(POP * n + get)
+++ else:
+++ write(_tuplesize2code[n])
+++ self.memoize(obj)
+++ return
+++
+++ # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple
+++ # has more than 3 elements.
+++ write(MARK)
+++ for element in obj:
+++ save(element)
+++
+++ if id(obj) in memo:
+++ # Subtle. d was not in memo when we entered save_tuple(), so
+++ # the process of saving the tuple's elements must have saved
+++ # the tuple itself: the tuple is recursive. The proper action
+++ # now is to throw away everything we put on the stack, and
+++ # simply GET the tuple (it's already constructed). This check
+++ # could have been done in the "for element" loop instead, but
+++ # recursive tuples are a rare thing.
+++ get = self.get(memo[id(obj)][0])
+++ if proto:
+++ write(POP_MARK + get)
+++ else: # proto 0 -- POP_MARK not available
+++ write(POP * (n+1) + get)
+++ return
+++
+++ # No recursion.
+++ self.write(TUPLE)
+++ self.memoize(obj)
+++
+++ dispatch[TupleType] = save_tuple
+++
+++ # save_empty_tuple() isn't used by anything in Python 2.3. However, I
+++ # found a Pickler subclass in Zope3 that calls it, so it's not harmless
+++ # to remove it.
+++ def save_empty_tuple(self, obj):
+++ self.write(EMPTY_TUPLE)
+++
+++ def save_list(self, obj):
+++ write = self.write
+++
+++ if self.bin:
+++ write(EMPTY_LIST)
+++ else: # proto 0 -- can't use EMPTY_LIST
+++ write(MARK + LIST)
+++
+++ self.memoize(obj)
+++ self._batch_appends(iter(obj))
+++
+++ dispatch[ListType] = save_list
+++
+++ # Keep in synch with cPickle's BATCHSIZE. Nothing will break if it gets
+++ # out of synch, though.
+++ _BATCHSIZE = 1000
+++
+++ def _batch_appends(self, items):
+++ # Helper to batch up APPENDS sequences
+++ save = self.save
+++ write = self.write
+++
+++ if not self.bin:
+++ for x in items:
+++ save(x)
+++ write(APPEND)
+++ return
+++
+++ r = xrange(self._BATCHSIZE)
+++ while items is not None:
+++ tmp = []
+++ for i in r:
+++ try:
+++ x = items.next()
+++ tmp.append(x)
+++ except StopIteration:
+++ items = None
+++ break
+++ n = len(tmp)
+++ if n > 1:
+++ write(MARK)
+++ for x in tmp:
+++ save(x)
+++ write(APPENDS)
+++ elif n:
+++ save(tmp[0])
+++ write(APPEND)
+++ # else tmp is empty, and we're done
+++
+++ def save_dict(self, obj):
+++ write = self.write
+++
+++ if self.bin:
+++ write(EMPTY_DICT)
+++ else: # proto 0 -- can't use EMPTY_DICT
+++ write(MARK + DICT)
+++
+++ self.memoize(obj)
+++ self._batch_setitems(obj.iteritems())
+++
+++ dispatch[DictionaryType] = save_dict
+++ if not PyStringMap is None:
+++ dispatch[PyStringMap] = save_dict
+++
+++ def _batch_setitems(self, items):
+++ # Helper to batch up SETITEMS sequences; proto >= 1 only
+++ save = self.save
+++ write = self.write
+++
+++ if not self.bin:
+++ for k, v in items:
+++ save(k)
+++ save(v)
+++ write(SETITEM)
+++ return
+++
+++ r = xrange(self._BATCHSIZE)
+++ while items is not None:
+++ tmp = []
+++ for i in r:
+++ try:
+++ tmp.append(items.next())
+++ except StopIteration:
+++ items = None
+++ break
+++ n = len(tmp)
+++ if n > 1:
+++ write(MARK)
+++ for k, v in tmp:
+++ save(k)
+++ save(v)
+++ write(SETITEMS)
+++ elif n:
+++ k, v = tmp[0]
+++ save(k)
+++ save(v)
+++ write(SETITEM)
+++ # else tmp is empty, and we're done
+++
+++ def save_inst(self, obj):
+++ cls = obj.__class__
+++
+++ memo = self.memo
+++ write = self.write
+++ save = self.save
+++
+++ if hasattr(obj, '__getinitargs__'):
+++ args = obj.__getinitargs__()
+++ len(args) # XXX Assert it's a sequence
+++ _keep_alive(args, memo)
+++ else:
+++ args = ()
+++
+++ write(MARK)
+++
+++ if self.bin:
+++ save(cls)
+++ for arg in args:
+++ save(arg)
+++ write(OBJ)
+++ else:
+++ for arg in args:
+++ save(arg)
+++ write(INST + cls.__module__ + '\n' + cls.__name__ + '\n')
+++
+++ self.memoize(obj)
+++
+++ try:
+++ getstate = obj.__getstate__
+++ except AttributeError:
+++ stuff = obj.__dict__
+++ else:
+++ stuff = getstate()
+++ _keep_alive(stuff, memo)
+++ save(stuff)
+++ write(BUILD)
+++
+++ dispatch[InstanceType] = save_inst
+++
+++ def save_global(self, obj, name=None, pack=struct.pack):
+++ write = self.write
+++ memo = self.memo
+++
+++ if name is None:
+++ name = obj.__name__
+++
+++ module = getattr(obj, "__module__", None)
+++ if module is None:
+++ module = whichmodule(obj, name)
+++
+++ try:
+++ __import__(module)
+++ mod = sys.modules[module]
+++ klass = getattr(mod, name)
+++ except (ImportError, KeyError, AttributeError):
+++ raise PicklingError(
+++ "Can't pickle %r: it's not found as %s.%s" %
+++ (obj, module, name))
+++ else:
+++ if klass is not obj:
+++ raise PicklingError(
+++ "Can't pickle %r: it's not the same object as %s.%s" %
+++ (obj, module, name))
+++
+++ if self.proto >= 2:
+++ code = _extension_registry.get((module, name))
+++ if code:
+++ assert code > 0
+++ if code <= 0xff:
+++ write(EXT1 + chr(code))
+++ elif code <= 0xffff:
+++ write("%c%c%c" % (EXT2, code&0xff, code>>8))
+++ else:
+++ write(EXT4 + pack("<i", code))
+++ return
+++
+++ write(GLOBAL + module + '\n' + name + '\n')
+++ self.memoize(obj)
+++
+++ dispatch[ClassType] = save_global
+++ dispatch[FunctionType] = save_global
+++ dispatch[BuiltinFunctionType] = save_global
+++ dispatch[TypeType] = save_global
+++
+++# Pickling helpers
+++
+++def _keep_alive(x, memo):
+++ """Keeps a reference to the object x in the memo.
+++
+++ Because we remember objects by their id, we have
+++ to assure that possibly temporary objects are kept
+++ alive by referencing them.
+++ We store a reference at the id of the memo, which should
+++ normally not be used unless someone tries to deepcopy
+++ the memo itself...
+++ """
+++ try:
+++ memo[id(memo)].append(x)
+++ except KeyError:
+++ # aha, this is the first one :-)
+++ memo[id(memo)]=[x]
+++
+++
+++# A cache for whichmodule(), mapping a function object to the name of
+++# the module in which the function was found.
+++
+++classmap = {} # called classmap for backwards compatibility
+++
+++def whichmodule(func, funcname):
+++ """Figure out the module in which a function occurs.
+++
+++ Search sys.modules for the module.
+++ Cache in classmap.
+++ Return a module name.
+++ If the function cannot be found, return "__main__".
+++ """
+++ # Python functions should always get an __module__ from their globals.
+++ mod = getattr(func, "__module__", None)
+++ if mod is not None:
+++ return mod
+++ if func in classmap:
+++ return classmap[func]
+++
+++ for name, module in sys.modules.items():
+++ if module is None:
+++ continue # skip dummy package entries
+++ if name != '__main__' and getattr(module, funcname, None) is func:
+++ break
+++ else:
+++ name = '__main__'
+++ classmap[func] = name
+++ return name
+++
+++
+++# Unpickling machinery
+++
+++class Unpickler:
+++
+++ def __init__(self, file):
+++ """This takes a file-like object for reading a pickle data stream.
+++
+++ The protocol version of the pickle is detected automatically, so no
+++ proto argument is needed.
+++
+++ The file-like object must have two methods, a read() method that
+++ takes an integer argument, and a readline() method that requires no
+++ arguments. Both methods should return a string. Thus file-like
+++ object can be a file object opened for reading, a StringIO object,
+++ or any other custom object that meets this interface.
+++ """
+++ self.readline = file.readline
+++ self.read = file.read
+++ self.memo = {}
+++
+++ def load(self):
+++ """Read a pickled object representation from the open file.
+++
+++ Return the reconstituted object hierarchy specified in the file.
+++ """
+++ self.mark = object() # any new unique object
+++ self.stack = []
+++ self.append = self.stack.append
+++ read = self.read
+++ dispatch = self.dispatch
+++ try:
+++ while 1:
+++ key = read(1)
+++ dispatch[key](self)
+++ except _Stop, stopinst:
+++ return stopinst.value
+++
+++ # Return largest index k such that self.stack[k] is self.mark.
+++ # If the stack doesn't contain a mark, eventually raises IndexError.
+++ # This could be sped by maintaining another stack, of indices at which
+++ # the mark appears. For that matter, the latter stack would suffice,
+++ # and we wouldn't need to push mark objects on self.stack at all.
+++ # Doing so is probably a good thing, though, since if the pickle is
+++ # corrupt (or hostile) we may get a clue from finding self.mark embedded
+++ # in unpickled objects.
+++ def marker(self):
+++ stack = self.stack
+++ mark = self.mark
+++ k = len(stack)-1
+++ while stack[k] is not mark: k = k-1
+++ return k
+++
+++ dispatch = {}
+++
+++ def load_eof(self):
+++ raise EOFError
+++ dispatch[''] = load_eof
+++
+++ def load_proto(self):
+++ proto = ord(self.read(1))
+++ if not 0 <= proto <= 2:
+++ raise ValueError, "unsupported pickle protocol: %d" % proto
+++ dispatch[PROTO] = load_proto
+++
+++ def load_persid(self):
+++ pid = self.readline()[:-1]
+++ self.append(self.persistent_load(pid))
+++ dispatch[PERSID] = load_persid
+++
+++ def load_binpersid(self):
+++ pid = self.stack.pop()
+++ self.append(self.persistent_load(pid))
+++ dispatch[BINPERSID] = load_binpersid
+++
+++ def load_none(self):
+++ self.append(None)
+++ dispatch[NONE] = load_none
+++
+++ def load_false(self):
+++ self.append(False)
+++ dispatch[NEWFALSE] = load_false
+++
+++ def load_true(self):
+++ self.append(True)
+++ dispatch[NEWTRUE] = load_true
+++
+++ def load_int(self):
+++ data = self.readline()
+++ if data == FALSE[1:]:
+++ val = False
+++ elif data == TRUE[1:]:
+++ val = True
+++ else:
+++ try:
+++ val = int(data)
+++ except ValueError:
+++ val = long(data)
+++ self.append(val)
+++ dispatch[INT] = load_int
+++
+++ def load_binint(self):
+++ self.append(mloads('i' + self.read(4)))
+++ dispatch[BININT] = load_binint
+++
+++ def load_binint1(self):
+++ self.append(ord(self.read(1)))
+++ dispatch[BININT1] = load_binint1
+++
+++ def load_binint2(self):
+++ self.append(mloads('i' + self.read(2) + '\000\000'))
+++ dispatch[BININT2] = load_binint2
+++
+++ def load_long(self):
+++ self.append(long(self.readline()[:-1], 0))
+++ dispatch[LONG] = load_long
+++
+++ def load_long1(self):
+++ n = ord(self.read(1))
+++ bytes = self.read(n)
+++ self.append(decode_long(bytes))
+++ dispatch[LONG1] = load_long1
+++
+++ def load_long4(self):
+++ n = mloads('i' + self.read(4))
+++ bytes = self.read(n)
+++ self.append(decode_long(bytes))
+++ dispatch[LONG4] = load_long4
+++
+++ def load_float(self):
+++ num = float(self.readline()[:-1])
+++ if num == 9999999999999.0: # very cheap trick
+++ num = float('inf')
+++ if num == -9999999999999.0: # very cheap trick
+++ num = float('-inf')
+++ self.append(num)
+++ dispatch[FLOAT] = load_float
+++
+++ def load_binfloat(self, unpack=struct.unpack):
+++ self.append(unpack('>d', self.read(8))[0])
+++ dispatch[BINFLOAT] = load_binfloat
+++
+++ def load_string(self):
+++ rep = self.readline()[:-1]
+++ for q in "\"'": # double or single quote
+++ if rep.startswith(q):
+++ if len(rep) < 2 or not rep.endswith(q):
+++ raise ValueError, "insecure string pickle"
+++ rep = rep[len(q):-len(q)]
+++ break
+++ else:
+++ raise ValueError, "insecure string pickle"
+++ self.append(rep.decode("string-escape"))
+++ dispatch[STRING] = load_string
+++
+++ def load_binstring(self):
+++ len = mloads('i' + self.read(4))
+++ self.append(self.read(len))
+++ dispatch[BINSTRING] = load_binstring
+++
+++ def load_unicode(self):
+++ self.append(unicode(self.readline()[:-1],'raw-unicode-escape'))
+++ dispatch[UNICODE] = load_unicode
+++
+++ def load_binunicode(self):
+++ len = mloads('i' + self.read(4))
+++ self.append(unicode(self.read(len),'utf-8'))
+++ dispatch[BINUNICODE] = load_binunicode
+++
+++ def load_short_binstring(self):
+++ len = ord(self.read(1))
+++ self.append(self.read(len))
+++ dispatch[SHORT_BINSTRING] = load_short_binstring
+++
+++ def load_tuple(self):
+++ k = self.marker()
+++ self.stack[k:] = [tuple(self.stack[k+1:])]
+++ dispatch[TUPLE] = load_tuple
+++
+++ def load_empty_tuple(self):
+++ self.stack.append(())
+++ dispatch[EMPTY_TUPLE] = load_empty_tuple
+++
+++ def load_tuple1(self):
+++ self.stack[-1] = (self.stack[-1],)
+++ dispatch[TUPLE1] = load_tuple1
+++
+++ def load_tuple2(self):
+++ self.stack[-2:] = [(self.stack[-2], self.stack[-1])]
+++ dispatch[TUPLE2] = load_tuple2
+++
+++ def load_tuple3(self):
+++ self.stack[-3:] = [(self.stack[-3], self.stack[-2], self.stack[-1])]
+++ dispatch[TUPLE3] = load_tuple3
+++
+++ def load_empty_list(self):
+++ self.stack.append([])
+++ dispatch[EMPTY_LIST] = load_empty_list
+++
+++ def load_empty_dictionary(self):
+++ self.stack.append({})
+++ dispatch[EMPTY_DICT] = load_empty_dictionary
+++
+++ def load_list(self):
+++ k = self.marker()
+++ self.stack[k:] = [self.stack[k+1:]]
+++ dispatch[LIST] = load_list
+++
+++ def load_dict(self):
+++ k = self.marker()
+++ d = {}
+++ items = self.stack[k+1:]
+++ for i in range(0, len(items), 2):
+++ key = items[i]
+++ value = items[i+1]
+++ d[key] = value
+++ self.stack[k:] = [d]
+++ dispatch[DICT] = load_dict
+++
+++ # INST and OBJ differ only in how they get a class object. It's not
+++ # only sensible to do the rest in a common routine, the two routines
+++ # previously diverged and grew different bugs.
+++ # klass is the class to instantiate, and k points to the topmost mark
+++ # object, following which are the arguments for klass.__init__.
+++ def _instantiate(self, klass, k):
+++ args = tuple(self.stack[k+1:])
+++ del self.stack[k:]
+++ instantiated = 0
+++ if (not args and
+++ type(klass) is ClassType and
+++ not hasattr(klass, "__getinitargs__")):
+++ try:
+++ value = _EmptyClass()
+++ value.__class__ = klass
+++ instantiated = 1
+++ except RuntimeError:
+++ # In restricted execution, assignment to inst.__class__ is
+++ # prohibited
+++ pass
+++ if not instantiated:
+++ try:
+++ value = klass(*args)
+++ except TypeError, err:
+++ raise TypeError, "in constructor for %s: %s" % (
+++ klass.__name__, str(err)), sys.exc_info()[2]
+++ self.append(value)
+++
+++ def load_inst(self):
+++ module = self.readline()[:-1]
+++ name = self.readline()[:-1]
+++ klass = self.find_class(module, name)
+++ self._instantiate(klass, self.marker())
+++ dispatch[INST] = load_inst
+++
+++ def load_obj(self):
+++ # Stack is ... markobject classobject arg1 arg2 ...
+++ k = self.marker()
+++ klass = self.stack.pop(k+1)
+++ self._instantiate(klass, k)
+++ dispatch[OBJ] = load_obj
+++
+++ def load_newobj(self):
+++ args = self.stack.pop()
+++ cls = self.stack[-1]
+++ obj = cls.__new__(cls, *args)
+++ self.stack[-1] = obj
+++ dispatch[NEWOBJ] = load_newobj
+++
+++ def load_global(self):
+++ module = self.readline()[:-1]
+++ name = self.readline()[:-1]
+++ klass = self.find_class(module, name)
+++ self.append(klass)
+++ dispatch[GLOBAL] = load_global
+++
+++ def load_ext1(self):
+++ code = ord(self.read(1))
+++ self.get_extension(code)
+++ dispatch[EXT1] = load_ext1
+++
+++ def load_ext2(self):
+++ code = mloads('i' + self.read(2) + '\000\000')
+++ self.get_extension(code)
+++ dispatch[EXT2] = load_ext2
+++
+++ def load_ext4(self):
+++ code = mloads('i' + self.read(4))
+++ self.get_extension(code)
+++ dispatch[EXT4] = load_ext4
+++
+++ def get_extension(self, code):
+++ nil = []
+++ obj = _extension_cache.get(code, nil)
+++ if obj is not nil:
+++ self.append(obj)
+++ return
+++ key = _inverted_registry.get(code)
+++ if not key:
+++ raise ValueError("unregistered extension code %d" % code)
+++ obj = self.find_class(*key)
+++ _extension_cache[code] = obj
+++ self.append(obj)
+++
+++ def find_class(self, module, name):
+++ # Subclasses may override this
+++ __import__(module)
+++ mod = sys.modules[module]
+++ klass = getattr(mod, name)
+++ return klass
+++
+++ def load_reduce(self):
+++ stack = self.stack
+++ args = stack.pop()
+++ func = stack[-1]
+++ value = func(*args)
+++ stack[-1] = value
+++ dispatch[REDUCE] = load_reduce
+++
+++ def load_pop(self):
+++ del self.stack[-1]
+++ dispatch[POP] = load_pop
+++
+++ def load_pop_mark(self):
+++ k = self.marker()
+++ del self.stack[k:]
+++ dispatch[POP_MARK] = load_pop_mark
+++
+++ def load_dup(self):
+++ self.append(self.stack[-1])
+++ dispatch[DUP] = load_dup
+++
+++ def load_get(self):
+++ self.append(self.memo[self.readline()[:-1]])
+++ dispatch[GET] = load_get
+++
+++ def load_binget(self):
+++ i = ord(self.read(1))
+++ self.append(self.memo[repr(i)])
+++ dispatch[BINGET] = load_binget
+++
+++ def load_long_binget(self):
+++ i = mloads('i' + self.read(4))
+++ self.append(self.memo[repr(i)])
+++ dispatch[LONG_BINGET] = load_long_binget
+++
+++ def load_put(self):
+++ self.memo[self.readline()[:-1]] = self.stack[-1]
+++ dispatch[PUT] = load_put
+++
+++ def load_binput(self):
+++ i = ord(self.read(1))
+++ self.memo[repr(i)] = self.stack[-1]
+++ dispatch[BINPUT] = load_binput
+++
+++ def load_long_binput(self):
+++ i = mloads('i' + self.read(4))
+++ self.memo[repr(i)] = self.stack[-1]
+++ dispatch[LONG_BINPUT] = load_long_binput
+++
+++ def load_append(self):
+++ stack = self.stack
+++ value = stack.pop()
+++ list = stack[-1]
+++ list.append(value)
+++ dispatch[APPEND] = load_append
+++
+++ def load_appends(self):
+++ stack = self.stack
+++ mark = self.marker()
+++ list = stack[mark - 1]
+++ list.extend(stack[mark + 1:])
+++ del stack[mark:]
+++ dispatch[APPENDS] = load_appends
+++
+++ def load_setitem(self):
+++ stack = self.stack
+++ value = stack.pop()
+++ key = stack.pop()
+++ dict = stack[-1]
+++ dict[key] = value
+++ dispatch[SETITEM] = load_setitem
+++
+++ def load_setitems(self):
+++ stack = self.stack
+++ mark = self.marker()
+++ dict = stack[mark - 1]
+++ for i in range(mark + 1, len(stack), 2):
+++ dict[stack[i]] = stack[i + 1]
+++
+++ del stack[mark:]
+++ dispatch[SETITEMS] = load_setitems
+++
+++ def load_build(self):
+++ stack = self.stack
+++ state = stack.pop()
+++ inst = stack[-1]
+++ setstate = getattr(inst, "__setstate__", None)
+++ if setstate:
+++ setstate(state)
+++ return
+++ slotstate = None
+++ if isinstance(state, tuple) and len(state) == 2:
+++ state, slotstate = state
+++ if state:
+++ try:
+++ d = inst.__dict__
+++ try:
+++ for k, v in state.iteritems():
+++ d[intern(k)] = v
+++ # keys in state don't have to be strings
+++ # don't blow up, but don't go out of our way
+++ except TypeError:
+++ d.update(state)
+++
+++ except RuntimeError:
+++ # XXX In restricted execution, the instance's __dict__
+++ # is not accessible. Use the old way of unpickling
+++ # the instance variables. This is a semantic
+++ # difference when unpickling in restricted
+++ # vs. unrestricted modes.
+++ # Note, however, that cPickle has never tried to do the
+++ # .update() business, and always uses
+++ # PyObject_SetItem(inst.__dict__, key, value) in a
+++ # loop over state.items().
+++ for k, v in state.items():
+++ setattr(inst, k, v)
+++ if slotstate:
+++ for k, v in slotstate.items():
+++ setattr(inst, k, v)
+++ dispatch[BUILD] = load_build
+++
+++ def load_mark(self):
+++ self.append(self.mark)
+++ dispatch[MARK] = load_mark
+++
+++ def load_stop(self):
+++ value = self.stack.pop()
+++ raise _Stop(value)
+++ dispatch[STOP] = load_stop
+++
+++# Helper class for load_inst/load_obj
+++
+++class _EmptyClass:
+++ pass
+++
+++# Encode/decode longs in linear time.
+++
+++import binascii as _binascii
+++
+++def encode_long(x):
+++ r"""Encode a long to a two's complement little-endian binary string.
+++ Note that 0L is a special case, returning an empty string, to save a
+++ byte in the LONG1 pickling context.
+++
+++ >>> encode_long(0L)
+++ ''
+++ >>> encode_long(255L)
+++ '\xff\x00'
+++ >>> encode_long(32767L)
+++ '\xff\x7f'
+++ >>> encode_long(-256L)
+++ '\x00\xff'
+++ >>> encode_long(-32768L)
+++ '\x00\x80'
+++ >>> encode_long(-128L)
+++ '\x80'
+++ >>> encode_long(127L)
+++ '\x7f'
+++ >>>
+++ """
+++
+++ if x == 0:
+++ return ''
+++ if x > 0:
+++ ashex = hex(x)
+++ assert ashex.startswith("0x")
+++ njunkchars = 2 + ashex.endswith('L')
+++ nibbles = len(ashex) - njunkchars
+++ if nibbles & 1:
+++ # need an even # of nibbles for unhexlify
+++ ashex = "0x0" + ashex[2:]
+++ elif int(ashex[2], 16) >= 8:
+++ # "looks negative", so need a byte of sign bits
+++ ashex = "0x00" + ashex[2:]
+++ else:
+++ # Build the 256's-complement: (1L << nbytes) + x. The trick is
+++ # to find the number of bytes in linear time (although that should
+++ # really be a constant-time task).
+++ ashex = hex(-x)
+++ assert ashex.startswith("0x")
+++ njunkchars = 2 + ashex.endswith('L')
+++ nibbles = len(ashex) - njunkchars
+++ if nibbles & 1:
+++ # Extend to a full byte.
+++ nibbles += 1
+++ nbits = nibbles * 4
+++ x += 1L << nbits
+++ assert x > 0
+++ ashex = hex(x)
+++ njunkchars = 2 + ashex.endswith('L')
+++ newnibbles = len(ashex) - njunkchars
+++ if newnibbles < nibbles:
+++ ashex = "0x" + "0" * (nibbles - newnibbles) + ashex[2:]
+++ if int(ashex[2], 16) < 8:
+++ # "looks positive", so need a byte of sign bits
+++ ashex = "0xff" + ashex[2:]
+++
+++ if ashex.endswith('L'):
+++ ashex = ashex[2:-1]
+++ else:
+++ ashex = ashex[2:]
+++ assert len(ashex) & 1 == 0, (x, ashex)
+++ binary = _binascii.unhexlify(ashex)
+++ return binary[::-1]
+++
+++def decode_long(data):
+++ r"""Decode a long from a two's complement little-endian binary string.
+++
+++ >>> decode_long('')
+++ 0L
+++ >>> decode_long("\xff\x00")
+++ 255L
+++ >>> decode_long("\xff\x7f")
+++ 32767L
+++ >>> decode_long("\x00\xff")
+++ -256L
+++ >>> decode_long("\x00\x80")
+++ -32768L
+++ >>> decode_long("\x80")
+++ -128L
+++ >>> decode_long("\x7f")
+++ 127L
+++ """
+++
+++ nbytes = len(data)
+++ if nbytes == 0:
+++ return 0L
+++ ashex = _binascii.hexlify(data[::-1])
+++ n = long(ashex, 16) # quadratic time before Python 2.3; linear now
+++ if data[-1] >= '\x80':
+++ n -= 1L << (nbytes * 8)
+++ return n
+++
+++# Shorthands
+++
+++try:
+++ from cStringIO import StringIO
+++except ImportError:
+++ from StringIO import StringIO
+++
+++def dump(obj, file, protocol=None):
+++ Pickler(file, protocol).dump(obj)
+++
+++def dumps(obj, protocol=None):
+++ file = StringIO()
+++ Pickler(file, protocol).dump(obj)
+++ return file.getvalue()
+++
+++def load(file):
+++ return Unpickler(file).load()
+++
+++def loads(str):
+++ file = StringIO(str)
+++ return Unpickler(file).load()
+++
+++# Doctest
+++
+++def _test():
+++ import doctest
+++ return doctest.testmod()
+++
+++if __name__ == "__main__":
+++ _test()
++diff -up mozilla-aurora/rebase/mystruct.py.rebase-dir mozilla-aurora/rebase/mystruct.py
++--- mozilla-aurora/rebase/mystruct.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/mystruct.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,15 @@
+++import struct
+++
+++def unpack_from(format, data, start):
+++ return struct.unpack(format, data[start:start + struct.calcsize(format)])
+++
+++class Struct:
+++ def __init__(self, format):
+++ self.format = format
+++ self.size = struct.calcsize(format)
+++ def unpack_from(self, buf, offset=0):
+++ return unpack_from(self.format, buf, offset)
+++ def pack(self, *args):
+++ return struct.pack(self.format, *args)
+++
+++
++diff -up mozilla-aurora/rebase/namedtuple.py.rebase-dir mozilla-aurora/rebase/namedtuple.py
++--- mozilla-aurora/rebase/namedtuple.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/namedtuple.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,147 @@
+++from operator import itemgetter as _itemgetter
+++from keyword import iskeyword as _iskeyword
+++import sys as _sys
+++
+++def namedtuple(typename, field_names, verbose=False, rename=False):
+++ """Returns a new subclass of tuple with named fields.
+++
+++ >>> Point = namedtuple('Point', 'x y')
+++ >>> Point.__doc__ # docstring for the new class
+++ 'Point(x, y)'
+++ >>> p = Point(11, y=22) # instantiate with positional args or keywords
+++ >>> p[0] + p[1] # indexable like a plain tuple
+++ 33
+++ >>> x, y = p # unpack like a regular tuple
+++ >>> x, y
+++ (11, 22)
+++ >>> p.x + p.y # fields also accessable by name
+++ 33
+++ >>> d = p._asdict() # convert to a dictionary
+++ >>> d['x']
+++ 11
+++ >>> Point(**d) # convert from a dictionary
+++ Point(x=11, y=22)
+++ >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
+++ Point(x=100, y=22)
+++
+++ """
+++
+++ # Parse and validate the field names. Validation serves two purposes,
+++ # generating informative error messages and preventing template injection attacks.
+++ if isinstance(field_names, basestring):
+++ field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
+++ field_names = tuple(map(str, field_names))
+++ if rename:
+++ names = list(field_names)
+++ seen = set()
+++ for i, name in enumerate(names):
+++ if (not min(c.isalnum() or c=='_' for c in name) or _iskeyword(name)
+++ or not name or name[0].isdigit() or name.startswith('_')
+++ or name in seen):
+++ names[i] = '_%d' % i
+++ seen.add(name)
+++ field_names = tuple(names)
+++ for name in (typename,) + field_names:
+++ if not min(c.isalnum() or c=='_' for c in name):
+++ raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
+++ if _iskeyword(name):
+++ raise ValueError('Type names and field names cannot be a keyword: %r' % name)
+++ if name[0].isdigit():
+++ raise ValueError('Type names and field names cannot start with a number: %r' % name)
+++ seen_names = set()
+++ for name in field_names:
+++ if name.startswith('_') and not rename:
+++ raise ValueError('Field names cannot start with an underscore: %r' % name)
+++ if name in seen_names:
+++ raise ValueError('Encountered duplicate field name: %r' % name)
+++ seen_names.add(name)
+++
+++ # Create and fill-in the class template
+++ numfields = len(field_names)
+++ argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
+++ reprtxt = ', '.join('%s=%%r' % name for name in field_names)
+++ template = '''class %(typename)s(tuple):
+++ '%(typename)s(%(argtxt)s)' \n
+++ __slots__ = () \n
+++ _fields = %(field_names)r \n
+++ def __new__(_cls, %(argtxt)s):
+++ return _tuple.__new__(_cls, (%(argtxt)s)) \n
+++ @classmethod
+++ def _make(cls, iterable, new=tuple.__new__, len=len):
+++ 'Make a new %(typename)s object from a sequence or iterable'
+++ result = new(cls, iterable)
+++ if len(result) != %(numfields)d:
+++ raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
+++ return result \n
+++ def __repr__(self):
+++ return '%(typename)s(%(reprtxt)s)' %% self \n
+++ def _asdict(self):
+++ 'Return a new dict which maps field names to their values'
+++ return dict(zip(self._fields, self)) \n
+++ def _replace(_self, **kwds):
+++ 'Return a new %(typename)s object replacing specified fields with new values'
+++ result = _self._make(map(kwds.pop, %(field_names)r, _self))
+++ if kwds:
+++ raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
+++ return result \n
+++ def __getnewargs__(self):
+++ return tuple(self) \n\n''' % locals()
+++ for i, name in enumerate(field_names):
+++ template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
+++ if verbose:
+++ print template
+++
+++ # Execute the template string in a temporary namespace
+++ namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
+++ _property=property, _tuple=tuple)
+++ try:
+++ exec template in namespace
+++ except SyntaxError, e:
+++ raise SyntaxError(e.message + ':\n' + template)
+++ result = namespace[typename]
+++
+++ # For pickling to work, the __module__ variable needs to be set to the frame
+++ # where the named tuple is created. Bypass this step in enviroments where
+++ # sys._getframe is not defined (Jython for example) or sys._getframe is not
+++ # defined for arguments greater than 0 (IronPython).
+++ try:
+++ result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
+++ except (AttributeError, ValueError):
+++ pass
+++
+++ return result
+++
+++
+++
+++
+++
+++
+++if __name__ == '__main__':
+++ # verify that instances can be pickled
+++ from cPickle import loads, dumps
+++ Point = namedtuple('Point', 'x, y', True)
+++ p = Point(x=10, y=20)
+++ assert p == loads(dumps(p, -1))
+++
+++ # test and demonstrate ability to override methods
+++ class Point(namedtuple('Point', 'x y')):
+++ @property
+++ def hypot(self):
+++ return (self.x ** 2 + self.y ** 2) ** 0.5
+++ def __str__(self):
+++ return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
+++
+++ for p in Point(3,4), Point(14,5), Point(9./7,6):
+++ print p
+++
+++ class Point(namedtuple('Point', 'x y')):
+++ 'Point class with optimized _make() and _replace() without error-checking'
+++ _make = classmethod(tuple.__new__)
+++ def _replace(self, _map=map, **kwds):
+++ return self._make(_map(kwds.get, ('x', 'y'), self))
+++
+++ print Point(11, 22)._replace(x=100)
+++
+++ import doctest
+++ TestResults = namedtuple('TestResults', 'failed attempted')
+++ print TestResults(*doctest.testmod())
++diff -up mozilla-aurora/rebase/ordereddict.py.rebase-dir mozilla-aurora/rebase/ordereddict.py
++--- mozilla-aurora/rebase/ordereddict.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/ordereddict.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,127 @@
+++# Copyright (c) 2009 Raymond Hettinger
+++#
+++# Permission is hereby granted, free of charge, to any person
+++# obtaining a copy of this software and associated documentation files
+++# (the "Software"), to deal in the Software without restriction,
+++# including without limitation the rights to use, copy, modify, merge,
+++# publish, distribute, sublicense, and/or sell copies of the Software,
+++# and to permit persons to whom the Software is furnished to do so,
+++# subject to the following conditions:
+++#
+++# The above copyright notice and this permission notice shall be
+++# included in all copies or substantial portions of the Software.
+++#
+++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+++# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+++# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+++# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+++# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+++# OTHER DEALINGS IN THE SOFTWARE.
+++
+++from UserDict import DictMixin
+++
+++class OrderedDict(dict, DictMixin):
+++
+++ def __init__(self, *args, **kwds):
+++ if len(args) > 1:
+++ raise TypeError('expected at most 1 arguments, got %d' % len(args))
+++ try:
+++ self.__end
+++ except AttributeError:
+++ self.clear()
+++ self.update(*args, **kwds)
+++
+++ def clear(self):
+++ self.__end = end = []
+++ end += [None, end, end] # sentinel node for doubly linked list
+++ self.__map = {} # key --> [key, prev, next]
+++ dict.clear(self)
+++
+++ def __setitem__(self, key, value):
+++ if key not in self:
+++ end = self.__end
+++ curr = end[1]
+++ curr[2] = end[1] = self.__map[key] = [key, curr, end]
+++ dict.__setitem__(self, key, value)
+++
+++ def __delitem__(self, key):
+++ dict.__delitem__(self, key)
+++ key, prev, next = self.__map.pop(key)
+++ prev[2] = next
+++ next[1] = prev
+++
+++ def __iter__(self):
+++ end = self.__end
+++ curr = end[2]
+++ while curr is not end:
+++ yield curr[0]
+++ curr = curr[2]
+++
+++ def __reversed__(self):
+++ end = self.__end
+++ curr = end[1]
+++ while curr is not end:
+++ yield curr[0]
+++ curr = curr[1]
+++
+++ def popitem(self, last=True):
+++ if not self:
+++ raise KeyError('dictionary is empty')
+++ if last:
+++ key = reversed(self).next()
+++ else:
+++ key = iter(self).next()
+++ value = self.pop(key)
+++ return key, value
+++
+++ def __reduce__(self):
+++ items = [[k, self[k]] for k in self]
+++ tmp = self.__map, self.__end
+++ del self.__map, self.__end
+++ inst_dict = vars(self).copy()
+++ self.__map, self.__end = tmp
+++ if inst_dict:
+++ return (self.__class__, (items,), inst_dict)
+++ return self.__class__, (items,)
+++
+++ def keys(self):
+++ return list(self)
+++
+++ setdefault = DictMixin.setdefault
+++ update = DictMixin.update
+++ pop = DictMixin.pop
+++ values = DictMixin.values
+++ items = DictMixin.items
+++ iterkeys = DictMixin.iterkeys
+++ itervalues = DictMixin.itervalues
+++ iteritems = DictMixin.iteritems
+++
+++ def __repr__(self):
+++ if not self:
+++ return '%s()' % (self.__class__.__name__,)
+++ return '%s(%r)' % (self.__class__.__name__, self.items())
+++
+++ def copy(self):
+++ return self.__class__(self)
+++
+++ @classmethod
+++ def fromkeys(cls, iterable, value=None):
+++ d = cls()
+++ for key in iterable:
+++ d[key] = value
+++ return d
+++
+++ def __eq__(self, other):
+++ if isinstance(other, OrderedDict):
+++ if len(self) != len(other):
+++ return False
+++ for p, q in zip(self.items(), other.items()):
+++ if p != q:
+++ return False
+++ return True
+++ return dict.__eq__(self, other)
+++
+++ def __ne__(self, other):
+++ return not self == other
++diff -up mozilla-aurora/rebase/rhrebase.py.rebase-dir mozilla-aurora/rebase/rhrebase.py
++--- mozilla-aurora/rebase/rhrebase.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/rhrebase.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,46 @@
+++def isIterable(l):
+++ if hasattr(l, '__iter__'):
+++ return True
+++ else:
+++ return False
+++
+++def print24(msg, file):
+++ if file:
+++ file.write(msg)
+++ else:
+++ print msg
+++
+++# hack to not import this file instead of system logging
+++def import_non_local(name, custom_name=None):
+++ import imp, sys
+++
+++ custom_name = custom_name or name
+++
+++ f, pathname, desc = imp.find_module(name, sys.path[1:])
+++ module = imp.load_module(custom_name, f, pathname, desc)
+++ #f.close()
+++
+++ return module
+++
+++def get_first_if_true(first, second, cond):
+++ if cond:
+++ return first
+++ else:
+++ return second
+++
+++def all(iterable):
+++ for element in iterable:
+++ if not element:
+++ return False
+++ return True
+++
+++def any(iterable):
+++ for element in iterable:
+++ if element:
+++ return True
+++ return False
+++
+++
+++
+++
+++
++diff -up mozilla-aurora/rebase/uuid.py.rebase-dir mozilla-aurora/rebase/uuid.py
++--- mozilla-aurora/rebase/uuid.py.rebase-dir 2014-07-28 18:25:25.000000000 +0200
+++++ mozilla-aurora/rebase/uuid.py 2014-07-28 18:25:25.000000000 +0200
++@@ -0,0 +1,476 @@
+++r"""UUID objects (universally unique identifiers) according to RFC 4122.
+++
+++This module provides immutable UUID objects (class UUID) and the functions
+++uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
+++UUIDs as specified in RFC 4122.
+++
+++If all you want is a unique ID, you should probably call uuid1() or uuid4().
+++Note that uuid1() may compromise privacy since it creates a UUID containing
+++the computer's network address. uuid4() creates a random UUID.
+++
+++Typical usage:
+++
+++ >>> import uuid
+++
+++ # make a UUID based on the host ID and current time
+++ >>> uuid.uuid1()
+++ UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
+++
+++ # make a UUID using an MD5 hash of a namespace UUID and a name
+++ >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
+++ UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
+++
+++ # make a random UUID
+++ >>> uuid.uuid4()
+++ UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
+++
+++ # make a UUID using a SHA-1 hash of a namespace UUID and a name
+++ >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
+++ UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
+++
+++ # make a UUID from a string of hex digits (braces and hyphens ignored)
+++ >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
+++
+++ # convert a UUID to a string of hex digits in standard form
+++ >>> str(x)
+++ '00010203-0405-0607-0809-0a0b0c0d0e0f'
+++
+++ # get the raw 16 bytes of the UUID
+++ >>> x.bytes
+++ '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
+++
+++ # make a UUID from a 16-byte string
+++ >>> uuid.UUID(bytes=x.bytes)
+++ UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
+++"""
+++
+++__author__ = 'Ka-Ping Yee <ping at zesty.ca>'
+++__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
+++__version__ = '$Revision: 1.30 $'.split()[1]
+++
+++RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
+++ 'reserved for NCS compatibility', 'specified in RFC 4122',
+++ 'reserved for Microsoft compatibility', 'reserved for future definition']
+++
+++class UUID(object):
+++ """Instances of the UUID class represent UUIDs as specified in RFC 4122.
+++ UUID objects are immutable, hashable, and usable as dictionary keys.
+++ Converting a UUID to a string with str() yields something in the form
+++ '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
+++ four possible forms: a similar string of hexadecimal digits, or a
+++ string of 16 raw bytes as an argument named 'bytes', or a tuple of
+++ six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
+++ 48-bit values respectively) as an argument named 'fields', or a single
+++ 128-bit integer as an argument named 'int'.
+++
+++ UUIDs have these read-only attributes:
+++
+++ bytes the UUID as a 16-byte string
+++
+++ fields a tuple of the six integer fields of the UUID,
+++ which are also available as six individual attributes
+++ and two derived attributes:
+++
+++ time_low the first 32 bits of the UUID
+++ time_mid the next 16 bits of the UUID
+++ time_hi_version the next 16 bits of the UUID
+++ clock_seq_hi_variant the next 8 bits of the UUID
+++ clock_seq_low the next 8 bits of the UUID
+++ node the last 48 bits of the UUID
+++
+++ time the 60-bit timestamp
+++ clock_seq the 14-bit sequence number
+++
+++ hex the UUID as a 32-character hexadecimal string
+++
+++ int the UUID as a 128-bit integer
+++
+++ urn the UUID as a URN as specified in RFC 4122
+++
+++ variant the UUID variant (one of the constants RESERVED_NCS,
+++ RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
+++
+++ version the UUID version number (1 through 5, meaningful only
+++ when the variant is RFC_4122)
+++ """
+++
+++ def __init__(self, hex=None, bytes=None, fields=None, int=None,
+++ version=None):
+++ r"""Create a UUID from either a string of 32 hexadecimal digits,
+++ a string of 16 bytes as the 'bytes' argument, a tuple of six
+++ integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
+++ 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
+++ the 'fields' argument, or a single 128-bit integer as the 'int'
+++ argument. When a string of hex digits is given, curly braces,
+++ hyphens, and a URN prefix are all optional. For example, these
+++ expressions all yield the same UUID:
+++
+++ UUID('{12345678-1234-5678-1234-567812345678}')
+++ UUID('12345678123456781234567812345678')
+++ UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
+++ UUID(bytes='\x12\x34\x56\x78'*4)
+++ UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
+++ UUID(int=0x12345678123456781234567812345678)
+++
+++ Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
+++ The 'version' argument is optional; if given, the resulting UUID
+++ will have its variant and version number set according to RFC 4122,
+++ overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
+++ """
+++
+++ if [hex, bytes, fields, int].count(None) != 3:
+++ raise TypeError('need just one of hex, bytes, fields, or int')
+++ if hex is not None:
+++ hex = hex.replace('urn:', '').replace('uuid:', '')
+++ hex = hex.strip('{}').replace('-', '')
+++ if len(hex) != 32:
+++ raise ValueError('badly formed hexadecimal UUID string')
+++ int = long(hex, 16)
+++ if bytes is not None:
+++ if len(bytes) != 16:
+++ raise ValueError('bytes is not a 16-char string')
+++ int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
+++ if fields is not None:
+++ if len(fields) != 6:
+++ raise ValueError('fields is not a 6-tuple')
+++ (time_low, time_mid, time_hi_version,
+++ clock_seq_hi_variant, clock_seq_low, node) = fields
+++ if not 0 <= time_low < 1<<32L:
+++ raise ValueError('field 1 out of range (need a 32-bit value)')
+++ if not 0 <= time_mid < 1<<16L:
+++ raise ValueError('field 2 out of range (need a 16-bit value)')
+++ if not 0 <= time_hi_version < 1<<16L:
+++ raise ValueError('field 3 out of range (need a 16-bit value)')
+++ if not 0 <= clock_seq_hi_variant < 1<<8L:
+++ raise ValueError('field 4 out of range (need an 8-bit value)')
+++ if not 0 <= clock_seq_low < 1<<8L:
+++ raise ValueError('field 5 out of range (need an 8-bit value)')
+++ if not 0 <= node < 1<<48L:
+++ raise ValueError('field 6 out of range (need a 48-bit value)')
+++ clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
+++ int = ((time_low << 96L) | (time_mid << 80L) |
+++ (time_hi_version << 64L) | (clock_seq << 48L) | node)
+++ if int is not None:
+++ if not 0 <= int < 1<<128L:
+++ raise ValueError('int is out of range (need a 128-bit value)')
+++ if version is not None:
+++ if not 1 <= version <= 5:
+++ raise ValueError('illegal version number')
+++ # Set the variant to RFC 4122.
+++ int &= ~(0xc000 << 48L)
+++ int |= 0x8000 << 48L
+++ # Set the version number.
+++ int &= ~(0xf000 << 64L)
+++ int |= version << 76L
+++ self.__dict__['int'] = int
+++
+++ def __cmp__(self, other):
+++ if isinstance(other, UUID):
+++ return cmp(self.int, other.int)
+++ return NotImplemented
+++
+++ def __hash__(self):
+++ return hash(self.int)
+++
+++ def __int__(self):
+++ return self.int
+++
+++ def __repr__(self):
+++ return 'UUID(%r)' % str(self)
+++
+++ def __setattr__(self, name, value):
+++ raise TypeError('UUID objects are immutable')
+++
+++ def __str__(self):
+++ hex = '%032x' % self.int
+++ return '%s-%s-%s-%s-%s' % (
+++ hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
+++
+++ def get_bytes(self):
+++ bytes = ''
+++ for shift in range(0, 128, 8):
+++ bytes = chr((self.int >> shift) & 0xff) + bytes
+++ return bytes
+++
+++ bytes = property(get_bytes)
+++
+++ def get_fields(self):
+++ return (self.time_low, self.time_mid, self.time_hi_version,
+++ self.clock_seq_hi_variant, self.clock_seq_low, self.node)
+++
+++ fields = property(get_fields)
+++
+++ def get_time_low(self):
+++ return self.int >> 96L
+++
+++ time_low = property(get_time_low)
+++
+++ def get_time_mid(self):
+++ return (self.int >> 80L) & 0xffff
+++
+++ time_mid = property(get_time_mid)
+++
+++ def get_time_hi_version(self):
+++ return (self.int >> 64L) & 0xffff
+++
+++ time_hi_version = property(get_time_hi_version)
+++
+++ def get_clock_seq_hi_variant(self):
+++ return (self.int >> 56L) & 0xff
+++
+++ clock_seq_hi_variant = property(get_clock_seq_hi_variant)
+++
+++ def get_clock_seq_low(self):
+++ return (self.int >> 48L) & 0xff
+++
+++ clock_seq_low = property(get_clock_seq_low)
+++
+++ def get_time(self):
+++ return (((self.time_hi_version & 0x0fffL) << 48L) |
+++ (self.time_mid << 32L) | self.time_low)
+++
+++ time = property(get_time)
+++
+++ def get_clock_seq(self):
+++ return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
+++ self.clock_seq_low)
+++
+++ clock_seq = property(get_clock_seq)
+++
+++ def get_node(self):
+++ return self.int & 0xffffffffffff
+++
+++ node = property(get_node)
+++
+++ def get_hex(self):
+++ return '%032x' % self.int
+++
+++ hex = property(get_hex)
+++
+++ def get_urn(self):
+++ return 'urn:uuid:' + str(self)
+++
+++ urn = property(get_urn)
+++
+++ def get_variant(self):
+++ if not self.int & (0x8000 << 48L):
+++ return RESERVED_NCS
+++ elif not self.int & (0x4000 << 48L):
+++ return RFC_4122
+++ elif not self.int & (0x2000 << 48L):
+++ return RESERVED_MICROSOFT
+++ else:
+++ return RESERVED_FUTURE
+++
+++ variant = property(get_variant)
+++
+++ def get_version(self):
+++ # The version bits are only meaningful for RFC 4122 UUIDs.
+++ if self.variant == RFC_4122:
+++ return int((self.int >> 76L) & 0xf)
+++
+++ version = property(get_version)
+++
+++def _ifconfig_getnode():
+++ """Get the hardware address on Unix by running ifconfig."""
+++ import os
+++ for dir in ['', '/sbin/', '/usr/sbin']:
+++ try:
+++ pipe = os.popen(os.path.join(dir, 'ifconfig'))
+++ except IOError:
+++ continue
+++ for line in pipe:
+++ words = line.lower().split()
+++ for i in range(len(words)):
+++ if words[i] in ['hwaddr', 'ether']:
+++ return int(words[i + 1].replace(':', ''), 16)
+++
+++def _ipconfig_getnode():
+++ """Get the hardware address on Windows by running ipconfig.exe."""
+++ import os, re
+++ dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
+++ try:
+++ import ctypes
+++ buffer = ctypes.create_string_buffer(300)
+++ ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
+++ dirs.insert(0, buffer.value.decode('mbcs'))
+++ except:
+++ pass
+++ for dir in dirs:
+++ try:
+++ pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
+++ except IOError:
+++ continue
+++ for line in pipe:
+++ value = line.split(':')[-1].strip().lower()
+++ if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
+++ return int(value.replace('-', ''), 16)
+++
+++def _netbios_getnode():
+++ """Get the hardware address on Windows using NetBIOS calls.
+++ See http://support.microsoft.com/kb/118623 for details."""
+++ import win32wnet, netbios
+++ ncb = netbios.NCB()
+++ ncb.Command = netbios.NCBENUM
+++ ncb.Buffer = adapters = netbios.LANA_ENUM()
+++ adapters._pack()
+++ if win32wnet.Netbios(ncb) != 0:
+++ return
+++ adapters._unpack()
+++ for i in range(adapters.length):
+++ ncb.Reset()
+++ ncb.Command = netbios.NCBRESET
+++ ncb.Lana_num = ord(adapters.lana[i])
+++ if win32wnet.Netbios(ncb) != 0:
+++ continue
+++ ncb.Reset()
+++ ncb.Command = netbios.NCBASTAT
+++ ncb.Lana_num = ord(adapters.lana[i])
+++ ncb.Callname = '*'.ljust(16)
+++ ncb.Buffer = status = netbios.ADAPTER_STATUS()
+++ if win32wnet.Netbios(ncb) != 0:
+++ continue
+++ status._unpack()
+++ bytes = map(ord, status.adapter_address)
+++ return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
+++ (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
+++
+++# Thanks to Thomas Heller for ctypes and for his help with its use here.
+++
+++# If ctypes is available, use it to find system routines for UUID generation.
+++_uuid_generate_random = _uuid_generate_time = _UuidCreate = None
+++try:
+++ import ctypes, ctypes.util
+++ _buffer = ctypes.create_string_buffer(16)
+++
+++ # The uuid_generate_* routines are provided by libuuid on at least
+++ # Linux and FreeBSD, and provided by libc on Mac OS X.
+++ for libname in ['uuid', 'c']:
+++ try:
+++ lib = ctypes.CDLL(ctypes.util.find_library(libname))
+++ except:
+++ continue
+++ if hasattr(lib, 'uuid_generate_random'):
+++ _uuid_generate_random = lib.uuid_generate_random
+++ if hasattr(lib, 'uuid_generate_time'):
+++ _uuid_generate_time = lib.uuid_generate_time
+++
+++ # On Windows prior to 2000, UuidCreate gives a UUID containing the
+++ # hardware address. On Windows 2000 and later, UuidCreate makes a
+++ # random UUID and UuidCreateSequential gives a UUID containing the
+++ # hardware address. These routines are provided by the RPC runtime.
+++ try:
+++ lib = ctypes.windll.rpcrt4
+++ except:
+++ lib = None
+++ _UuidCreate = getattr(lib, 'UuidCreateSequential',
+++ getattr(lib, 'UuidCreate', None))
+++except:
+++ pass
+++
+++def _unixdll_getnode():
+++ """Get the hardware address on Unix using ctypes."""
+++ _uuid_generate_time(_buffer)
+++ return UUID(bytes=_buffer.raw).node
+++
+++def _windll_getnode():
+++ """Get the hardware address on Windows using ctypes."""
+++ if _UuidCreate(_buffer) == 0:
+++ return UUID(bytes=_buffer.raw).node
+++
+++def _random_getnode():
+++ """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
+++ import random
+++ return random.randrange(0, 1<<48L) | 0x010000000000L
+++
+++_node = None
+++
+++def getnode():
+++ """Get the hardware address as a 48-bit integer. The first time this
+++ runs, it may launch a separate program, which could be quite slow. If
+++ all attempts to obtain the hardware address fail, we choose a random
+++ 48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
+++
+++ global _node
+++ if _node is not None:
+++ return _node
+++
+++ import sys
+++ if sys.platform == 'win32':
+++ getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+++ else:
+++ getters = [_unixdll_getnode, _ifconfig_getnode]
+++
+++ for getter in getters + [_random_getnode]:
+++ try:
+++ _node = getter()
+++ except:
+++ continue
+++ if _node is not None:
+++ return _node
+++
+++def uuid1(node=None, clock_seq=None):
+++ """Generate a UUID from a host ID, sequence number, and the current time.
+++ If 'node' is not given, getnode() is used to obtain the hardware
+++ address. If 'clock_seq' is given, it is used as the sequence number;
+++ otherwise a random 14-bit sequence number is chosen."""
+++
+++ # When the system provides a version-1 UUID generator, use it (but don't
+++ # use UuidCreate here because its UUIDs don't conform to RFC 4122).
+++ if _uuid_generate_time and node is clock_seq is None:
+++ _uuid_generate_time(_buffer)
+++ return UUID(bytes=_buffer.raw)
+++
+++ import time
+++ nanoseconds = int(time.time() * 1e9)
+++ # 0x01b21dd213814000 is the number of 100-ns intervals between the
+++ # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
+++ timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
+++ if clock_seq is None:
+++ import random
+++ clock_seq = random.randrange(1<<14L) # instead of stable storage
+++ time_low = timestamp & 0xffffffffL
+++ time_mid = (timestamp >> 32L) & 0xffffL
+++ time_hi_version = (timestamp >> 48L) & 0x0fffL
+++ clock_seq_low = clock_seq & 0xffL
+++ clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
+++ if node is None:
+++ node = getnode()
+++ return UUID(fields=(time_low, time_mid, time_hi_version,
+++ clock_seq_hi_variant, clock_seq_low, node), version=1)
+++
+++def uuid3(namespace, name):
+++ """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
+++ import md5
+++ hash = md5.md5(namespace.bytes + name).digest()
+++ return UUID(bytes=hash[:16], version=3)
+++
+++def uuid4():
+++ """Generate a random UUID."""
+++
+++ # When the system provides a version-4 UUID generator, use it.
+++ if _uuid_generate_random:
+++ _uuid_generate_random(_buffer)
+++ return UUID(bytes=_buffer.raw)
+++
+++ # Otherwise, get randomness from urandom or the 'random' module.
+++ try:
+++ import os
+++ return UUID(bytes=os.urandom(16), version=4)
+++ except:
+++ import random
+++ bytes = [chr(random.randrange(256)) for i in range(16)]
+++ return UUID(bytes=bytes, version=4)
+++
+++def uuid5(namespace, name):
+++ """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
+++ import sha
+++ hash = sha.sha(namespace.bytes + name).digest()
+++ return UUID(bytes=hash[:16], version=5)
+++
+++# The following standard UUIDs are for use with uuid3() or uuid5().
+++
+++NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
+++NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
+++NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
+++NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
diff --cc sources
index 1244ce3,0a4f031..5489530
--- a/sources
+++ b/sources
@@@ -1,4 -1,3 +1,6 @@@
- 689eece85bd132adc72413158c7a46df lightning-2.6.5.source.tar.bz2
- aaeef94716b602924b539a7c700053ee l10n-2.6.5.tar.xz
+ 3d9c8a52ba75fcee5655839ab00cbda4 lightning-3.3.source.tar.bz2
+ 620cbeb932d910e1e33bebc47fff2f9c l10n-3.3.tar.xz
+ 0bbe3a2e5e4cac040013733aca159d89 simplejson-2.1.1.tar.gz
+711afa1062a1d2c4a67acdf02a33d86e pysqlite-2.6.3.tar.gz
+bd639f9b0eac4c42497034dec2ec0c2b setuptools-0.6c11-py2.4.egg
++a8ee9a58dc887d4a1942da4afec402f0 virtualtools-1.7.2.zip
diff --cc thunderbird-lightning-lightning.patch
index 0000000,0000000..abbbdef
new file mode 100644
--- /dev/null
+++ b/thunderbird-lightning-lightning.patch
@@@ -1,0 -1,0 +1,9 @@@
++diff -up thunderbird-lightning-3.3/comm-esr31/calendar/providers/gdata/makeversion.py.lightning thunderbird-lightning-3.3/comm-esr31/calendar/providers/gdata/makeversion.py
++--- thunderbird-lightning-3.3/comm-esr31/calendar/providers/gdata/makeversion.py.lightning 2014-07-17 18:04:05.000000000 -0600
+++++ thunderbird-lightning-3.3/comm-esr31/calendar/providers/gdata/makeversion.py 2014-10-23 16:40:44.959935874 -0600
++@@ -9,4 +9,4 @@ import re
++ # Lightning 1.2 -> gdata-provider 0.11
++ # Lightning 1.3a1 -> gdata-provider 0.12pre
++ v = re.search(r"(\d+\.\d+)([a-z]\d+)?", sys.argv[1])
++-print "{0:.2f}".format((float(v.group(1)) - 0.1)/10) + (v.lastindex == 2 and "pre" or "")
+++print "%.2f" % ((float(v.group(1)) - 0.1)/10) + (v.lastindex == 2 and "pre" or "")
diff --cc thunderbird-lightning.spec
index ee29246,b93efc4..6789e7a
--- a/thunderbird-lightning.spec
+++ b/thunderbird-lightning.spec
@@@ -43,36 -66,39 +66,45 @@@ Source1: mklangsource.s
Source2: l10n-%{version}.tar.xz
# Config file for compilation
Source10: thunderbird-mozconfig
+Source31: pysqlite-2.6.3.tar.gz
# Finds requirements provided outside of the current file set
Source100: find-external-requires
+ Source200: simplejson-2.1.1.tar.gz
+Source201: setuptools-0.6c11-py2.4.egg
++Source202: virtualtools-1.7.2.zip
- # Mozilla (XULRunner) patches
- Patch0: thunderbird-version.patch
+ # Build patches
Patch1: mozilla-build-arm.patch
- # Fix build on secondary arches (patches copied from xulrunner)
- Patch2: xulrunner-10.0-secondary-ipc.patch
-
- Patch099: mozilla-build.patch
- Patch100: xulrunner-2.0-chromium-types.patch
- Patch101: mozilla-abort.patch
- Patch103: xulrunner-gc-sections-ppc.patch
- # For RHEL5 only
- Patch201: mozilla-python.patch
- Patch204: xulrunner-missing-pysqlite.patch
- Patch210: mozilla-python2.patch
+ Patch15: disable-webm.patch
+ Patch16: nullptr.patch
+
-# EL6 Specific
-# Use old python
-Patch097: mozilla-python.patch
++# Xulrunner patches
+ Patch104: rhbz-966424.patch
+ Patch105: xulrunner-24.0-jemalloc-ppc.patch
+ Patch106: xulrunner-24.0-s390-inlines.patch
+ Patch107: firefox-system-nss-3.16.2.patch
+ Patch108: remove-ogg.patch
++Patch214: pango-backport.patch
++Patch215: mozilla-python3.patch
++Patch216: rebase-dir.patch
# Thunderbird specific
+ Patch301: thunderbird-objdir.patch
+ Patch302: array_len.patch
- # Lightning
++# Lightning specifig
++Patch400: thunderbird-lightning-lightning.patch
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ %if %{?system_nss}
BuildRequires: nspr-devel >= %{nspr_version}
BuildRequires: nss-devel >= %{nss_version}
- %if 0%{?fedora} > 15
+ Requires: nspr >= %{nspr_build_version}
+ Requires: nss >= %{nss_build_version}
+ %if 0%{?fedora}
BuildRequires: nss-static
%endif
+ %endif
-BuildRequires: cairo-devel >= %{cairo_version}
BuildRequires: libnotify-devel >= %{libnotify_version}
BuildRequires: libpng-devel
BuildRequires: libjpeg-devel
@@@ -89,6 -115,10 +121,9 @@@ BuildRequires: pango-deve
BuildRequires: freetype-devel >= %{freetype_version}
BuildRequires: libXt-devel
BuildRequires: libXrender-devel
-BuildRequires: hunspell-devel
+ %if %{?system_sqlite}
+ BuildRequires: sqlite-devel >= %{sqlite_version}
+ %endif
BuildRequires: startup-notification-devel
BuildRequires: alsa-lib-devel
BuildRequires: autoconf213
@@@ -97,10 -128,10 +132,10 @@@ BuildRequires: python-setuptool
BuildRequires: python-simplejson
BuildRequires: yasm
BuildRequires: mesa-libGL-devel
- # FIXME should be omitted when building without system sqlite?
- BuildRequires: sqlite-devel
-BuildRequires: pulseaudio-libs-devel
+BuildRequires: gcc44-c++
-
+ %if %{?system_ffi}
+ BuildRequires: libffi-devel
+ %endif
Requires: thunderbird >= %{thunderbird_version}
Requires: thunderbird < %{thunderbird_next_version}
Obsoletes: thunderbird-lightning-wcap <= 0.8
@@@ -108,12 -141,12 +145,16 @@@ Provides: thunderbird-lightning-w
AutoProv: 0
%global _use_internal_dependency_generator 0
%global __find_requires %{SOURCE100}
+ %else
+ %global __provides_exclude_from ^%{_libdir}/mozilla/.*$
+ %global __requires_exclude_from ^%{_libdir}/mozilla/.*$
+ %endif
-
+# Build fails on ppc for now
+# https://bugzilla.redhat.com/show_bug.cgi?id=924354
+ExcludeArch: ppc
+
+
%description
Lightning brings the Sunbird calendar to the popular email client,
Mozilla Thunderbird. Since it's an extension, Lightning is tightly
@@@ -139,51 -171,77 +180,101 @@@ your bug already has a solution
%setup -q -c -a 2
cd %{tarballdir}
- sed -e 's/__RPM_VERSION_INTERNAL__/%{version_internal}/' %{P:%%PATCH0} \
- > version.patch
- %{__patch} -p1 -b --suffix .version --fuzz=0 < version.patch
+ # xulrunner patches
+ cd mozilla
-%patch097 -p1 -b .python
+ %patch104 -p1 -b .rhbz-966424
+ %patch105 -p2 -b .jemalloc-ppc
+ %patch106 -p1 -b .s390
+ %patch107 -p3 -b .system_nss
+ %patch108 -p1 -b .remove-ogg
++%patch214 -p1 -b .pango-backport
++%patch216 -p1 -b .rebase-dir
+ %patch15 -p1 -b .disable-webm
+ %patch16 -p1 -b .nullptr
+ cd -
+
+ # thunderbird specific patches
+ %patch301 -p2 -b .objdir
+ %patch302 -p1 -b .array_len
++%patch215 -p1 -b .python3
++
++# lightning specific
++%patch400 -p2 -b .lightning
+
+ #sed -e 's/__RPM_VERSION_INTERNAL__/%{version_internal}/' %{P:%%PATCH0} \
+ # > version.patch
+ #%{__patch} -p1 -b --suffix .version --fuzz=0 < version.patch
cd mozilla
%patch1 -p2 -b .arm-fix
- %patch2 -p3 -b .secondary-ipc
- %patch099 -p1 -b .build
- %patch100 -p2 -b .chromium-types
- %patch101 -p1 -b .abort
- %patch201 -p1 -b .python
- %patch204 -p1 -b .pysqlite
- %patch210 -p1 -b .python2
- %patch103 -p2 -b .gc-sections
cd ..
+# thunderbird specific patches
+
%{__rm} -f .mozconfig
%{__cp} %{SOURCE10} .mozconfig
+
++rm -rf mozilla/python/virtualenv
++unzip %{SOURCE202} -d mozilla/python/
++mv mozilla/python/virtualenv-1.7.2 mozilla/python/virtualenv
++tar xz -C `pwd`/mozilla/rebase --strip-components=1 -f %{SOURCE200} simplejson-2.1.1/simplejson
++#%{__cp} %{SOURCE200} python/virtualenv/
+%{__cp} %{SOURCE201} mozilla/python/virtualenv/
+
++cd mozilla/python/mozbuild/mozbuild/backend/
++ln -s ../preprocessor.py
++ln -s ../makeutil.py
++ln -s ../pythonutil.py
++ln -s ../util.py
++cd -
++
+# RHEL 5 mozconfig changes:
+echo "ac_add_options --disable-system-hunspell" >> .mozconfig
+echo "ac_add_options --disable-libnotify" >> .mozconfig
+echo "ac_add_options --disable-methodjit" >> .mozconfig
+echo "ac_add_options --disable-skia" >> .mozconfig
+
- # Disable webm
- echo "ac_add_options --without-system-libvpx" >> .mozconfig
- echo "ac_add_options --disable-webm" >> .mozconfig
- echo "ac_add_options --disable-webrtc" >> .mozconfig
- echo "ac_add_options --disable-ogg" >> .mozconfig
-
- # s390(x) fails to start with jemalloc enabled
- %ifarch s390 s390x
- echo "ac_add_options --disable-jemalloc" >> .mozconfig
+ %if %{?system_nss}
+ echo "ac_add_options --with-system-nspr" >> .mozconfig
+ echo "ac_add_options --with-system-nss" >> .mozconfig
+ %else
+ echo "ac_add_options --without-system-nspr" >> .mozconfig
+ echo "ac_add_options --without-system-nss" >> .mozconfig
%endif
%ifarch %{arm}
echo "ac_add_options --disable-elf-hack" >> .mozconfig
%endif
-%ifnarch %{ix86} x86_64
-echo "ac_add_options --disable-webrtc" >> .mozconfig
-%endif
+# Copy pysqlite tarball to location from where it will be installed, for RHEL5 only
+%{__cp} %{SOURCE31} mozilla/testing/mozbase/mozprofile
+ %if %{?system_sqlite}
+ echo "ac_add_options --enable-system-sqlite" >> .mozconfig
+ %else
+ echo "ac_add_options --disable-system-sqlite" >> .mozconfig
+ %endif
+
+ %if %{?system_ffi}
+ echo "ac_add_options --enable-system-ffi" >> .mozconfig
+ %endif
+
+ %ifnarch %{ix86} x86_64
+ echo "ac_add_options --disable-methodjit" >> .mozconfig
+ echo "ac_add_options --disable-monoic" >> .mozconfig
+ echo "ac_add_options --disable-polyic" >> .mozconfig
+ echo "ac_add_options --disable-tracejit" >> .mozconfig
+ %endif
+
-echo "ac_add_options --enable-system-hunspell" >> .mozconfig
-echo "ac_add_options --enable-libnotify" >> .mozconfig
+ echo "ac_add_options --enable-startup-notification" >> .mozconfig
+ echo "ac_add_options --without-system-libvpx" >> .mozconfig
+ echo "ac_add_options --disable-webm" >> .mozconfig
+ echo "ac_add_options --disable-webrtc" >> .mozconfig
+ echo "ac_add_options --disable-ogg" >> .mozconfig
+ echo "ac_add_options --disable-opus" >> .mozconfig
+
+ echo "ac_add_options --disable-debug" >> .mozconfig
+ echo "ac_add_options --enable-optimize" >> .mozconfig
+
# Fix permissions
find -name \*.js -type f | xargs chmod -x
@@@ -203,20 -277,10 +313,18 @@@ MOZ_APP_DIR=%{mozappdir
#
# Disable C++ exceptions since Mozilla code is not exception-safe
#
-MOZ_OPT_FLAGS=$(echo "$RPM_OPT_FLAGS -fpermissive" | \
+MOZ_OPT_FLAGS=$(echo "$RPM_OPT_FLAGS" | \
%{__sed} -e 's/-Wall//')
+%ifarch %{ix86}
+# i386 target is missing sync_bool_compare_and_swap/sync_add_and_fetch
+# gcc build-in functions
+MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-march=i386/-march=i686/')
+%endif
+export CC=gcc44
+export GCC=gcc44
+export CXX=g++44
- # https://bugzilla.redhat.com/show_bug.cgi?id=1037355
- MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wformat-security -Wformat"
export CFLAGS=$MOZ_OPT_FLAGS
--export CXXFLAGS=$MOZ_OPT_FLAGS
++export CXXFLAGS="$MOZ_OPT_FLAGS -fpermissive"
export PREFIX='%{_prefix}'
export LIBDIR='%{_libdir}'
diff --cc thunderbird-mozconfig
index ea72cff,2a45066..47f9744
--- a/thunderbird-mozconfig
+++ b/thunderbird-mozconfig
@@@ -33,10 -28,13 +28,15 @@@ ac_add_options --enable-startup-notific
ac_add_options --disable-libjpeg-turbo
ac_add_options --disable-cpp-exceptions
ac_add_options --disable-updater
- ac_add_options --disable-elf-hack
ac_add_options --disable-gstreamer
+ac_add_options --disable-gio
- ac_add_options --enable-gnomevfs
+ ac_add_options --enable-cpp-rtti
++ac_add_options --disable-pulseaudio
+
+ # thunderbird related
+ ac_add_options --enable-xinerama
+ ac_add_options --disable-xprint
+ ac_add_options --enable-safe-browsing
# lightning related
ac_add_options --enable-calendar
More information about the scm-commits
mailing list