Backed out 3 changesets (bug 1388013) for build bustages e.g. ../python/mozbuild/mozpack/test/test_files.py on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Thu, 31 May 2018 11:48:19 +0300
changeset 474861 ba9528133000abdb4cfd0d1fc7587ac63508520e
parent 474860 4cab0dc8b7d9bec46ec24334a425e5d96a21002c
child 474862 646b7e8eb69b042e337ee97f3d1e7d3b40f2c2f5
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1388013
milestone62.0a1
backs outeea857170a418231418d27bda675446e2d21b2b8
c55bfefbd4e1786bd90ed173bbef547dff8d84ef
3a163da2b21b5b835c6a0e41cd0d35425cc84edb
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1388013) for build bustages e.g. ../python/mozbuild/mozpack/test/test_files.py on a CLOSED TREE Backed out changeset eea857170a41 (bug 1388013) Backed out changeset c55bfefbd4e1 (bug 1388013) Backed out changeset 3a163da2b21b (bug 1388013)
Pipfile
Pipfile.lock
python/Pipfile
python/Pipfile.lock
python/mach/setup.py
python/mach_commands.py
python/mozbuild/mozbuild/base.py
python/mozbuild/mozbuild/virtualenv.py
python/mozversioncontrol/setup.py
testing/mozbase/mozrunner/setup.py
third_party/python/jsmin/LICENSE.txt
third_party/python/jsmin/MANIFEST.in
third_party/python/jsmin/PKG-INFO
third_party/python/jsmin/README.rst
third_party/python/jsmin/jsmin/__init__.py
third_party/python/jsmin/jsmin/__main__.py
third_party/python/jsmin/jsmin/test.py
--- a/Pipfile
+++ b/Pipfile
@@ -6,12 +6,11 @@ name = "pypi"
 [dev-packages]
 
 [packages]
 pipenv = "==2018.5.18"
 virtualenv = "==15.2.0"
 six = "==1.10.0"
 attrs = "==18.1.0"
 pytest = "==3.2.5"
-jsmin = "==2.0.11"
 
 [requires]
 python_version = "2.7"
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,12 +1,12 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "4b5d386952702feee696b0166421981cae6fad8c96b233923e0343095c38903e"
+            "sha256": "cfd63f783e0107d8c5ebc5f17ee5c6644825657a4504e5529ceaabb293837659"
         },
         "pipfile-spec": 6,
         "requires": {
             "python_version": "2.7"
         },
         "sources": [
             {
                 "name": "pypi",
@@ -26,23 +26,16 @@
         },
         "certifi": {
             "hashes": [
                 "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
                 "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
             ],
             "version": "==2018.4.16"
         },
-        "jsmin": {
-            "hashes": [
-                "sha256:7898a19e17a89b1e294cce4a43b107441630eeacae4cf9595961eb39e1a716d1"
-            ],
-            "index": "pypi",
-            "version": "==2.0.11"
-        },
         "pipenv": {
             "hashes": [
                 "sha256:04b9a8b02a3ff12a5502b335850cfdb192adcfd1d6bbdb7a7c47cae9ab9ddece",
                 "sha256:e96d5bfa6822a17b2200d455aa5f9002c14361c50df1b1e51921479d7c09e741"
             ],
             "index": "pypi",
             "version": "==2018.5.18"
         },
deleted file mode 100644
--- a/python/Pipfile
+++ /dev/null
@@ -1,36 +0,0 @@
-[[source]]
-url = "https://pypi.org/simple"
-verify_ssl = true
-name = "pypi"
-
-[packages]
-"d5b4a14" = {path = "./mach"}
-"8ddb376" = {path = "./mozbuild"}
-"b3ddbcf" = {path = "./mozterm"}
-"38a4a9a" = {path = "./mozversioncontrol"}
-"26d92fb" = {path = "./../config/mozunit"}
-"cea2946" = {path = "./../testing/mozbase/manifestparser"}
-"ffcf6e6" = {path = "./../testing/mozbase/mozcrash"}
-"195ae2e" = {path = "./../testing/mozbase/mozdebug"}
-"8dab59a" = {path = "./../testing/mozbase/mozdevice"}
-"58d0848" = {path = "./../testing/mozbase/mozfile"}
-"fd0b608" = {path = "./../testing/mozbase/mozhttpd"}
-"7329809" = {path = "./../testing/mozbase/mozinfo"}
-"501835d" = {path = "./../testing/mozbase/mozinstall"}
-"807c1c5" = {path = "./../testing/mozbase/mozlog"}
-"e09e103" = {path = "./../testing/mozbase/moznetwork"}
-"132adec" = {path = "./../testing/mozbase/mozprocess"}
-"d88f467" = {path = "./../testing/mozbase/mozprofile"}
-"1de94f2" = {path = "./../testing/mozbase/mozrunner"}
-"6477f20" = {path = "./../testing/mozbase/moztest"}
-"f1d74ca" = {path = "./../testing/mozbase/mozversion"}
-"47200d8" = {path = "./../third_party/python/futures", markers="python_version < '3'"}
-"110bcc4" = {path = "./../third_party/python/jsmin"}
-"c49d32a" = {path = "./../third_party/python/mock-1.0.0", markers="python_version < '3.3'"}
-"c2c21d9" = {path = "./../third_party/python/py"}
-"f4b00e9" = {path = "./../third_party/python/pytest"}
-"053111f" = {path = "./../third_party/python/requests"}
-"d250320" = {path = "./../third_party/python/six"}
-"f1de77a" = {path = "./../third_party/python/which", markers="python_version < '3.3'"}
-
-[dev-packages]
deleted file mode 100644
--- a/python/Pipfile.lock
+++ /dev/null
@@ -1,106 +0,0 @@
-{
-    "_meta": {
-        "hash": {
-            "sha256": "dfc219f64edc7715acdb35e03dcee665ec26908c18a58d3a3a88dda3ab393b17"
-        },
-        "pipfile-spec": 6,
-        "requires": {},
-        "sources": [
-            {
-                "name": "pypi",
-                "url": "https://pypi.org/simple",
-                "verify_ssl": true
-            }
-        ]
-    },
-    "default": {
-        "053111f": {
-            "path": "./../third_party/python/requests"
-        },
-        "110bcc4": {
-            "path": "./../third_party/python/jsmin"
-        },
-        "132adec": {
-            "path": "./../testing/mozbase/mozprocess"
-        },
-        "195ae2e": {
-            "path": "./../testing/mozbase/mozdebug"
-        },
-        "1de94f2": {
-            "path": "./../testing/mozbase/mozrunner"
-        },
-        "26d92fb": {
-            "path": "./../config/mozunit"
-        },
-        "38a4a9a": {
-            "path": "./mozversioncontrol"
-        },
-        "47200d8": {
-            "markers": "python_version < '3'",
-            "path": "./../third_party/python/futures"
-        },
-        "501835d": {
-            "path": "./../testing/mozbase/mozinstall"
-        },
-        "58d0848": {
-            "path": "./../testing/mozbase/mozfile"
-        },
-        "6477f20": {
-            "path": "./../testing/mozbase/moztest"
-        },
-        "7329809": {
-            "path": "./../testing/mozbase/mozinfo"
-        },
-        "807c1c5": {
-            "path": "./../testing/mozbase/mozlog"
-        },
-        "8dab59a": {
-            "path": "./../testing/mozbase/mozdevice"
-        },
-        "8ddb376": {
-            "path": "./mozbuild"
-        },
-        "b3ddbcf": {
-            "path": "./mozterm"
-        },
-        "c2c21d9": {
-            "path": "./../third_party/python/py"
-        },
-        "c49d32a": {
-            "markers": "python_version < '3.3'",
-            "path": "./../third_party/python/mock-1.0.0"
-        },
-        "cea2946": {
-            "path": "./../testing/mozbase/manifestparser"
-        },
-        "d250320": {
-            "path": "./../third_party/python/six"
-        },
-        "d5b4a14": {
-            "path": "./mach"
-        },
-        "d88f467": {
-            "path": "./../testing/mozbase/mozprofile"
-        },
-        "e09e103": {
-            "path": "./../testing/mozbase/moznetwork"
-        },
-        "f1d74ca": {
-            "path": "./../testing/mozbase/mozversion"
-        },
-        "f1de77a": {
-            "markers": "python_version < '3.3'",
-            "path": "./../third_party/python/which"
-        },
-        "f4b00e9": {
-            "path": "./../third_party/python/pytest"
-        },
-        "fd0b608": {
-            "path": "./../testing/mozbase/mozhttpd"
-        },
-        "ffcf6e6": {
-            "path": "./../testing/mozbase/mozcrash"
-        }
-    },
-    "develop": {}
-}
--- a/python/mach/setup.py
+++ b/python/mach/setup.py
@@ -15,17 +15,17 @@ README = open('README.rst').read()
 setup(
     name='mach',
     description='Generic command line command dispatching framework.',
     long_description=README,
     license='MPL 2.0',
     author='Gregory Szorc',
     author_email='gregory.szorc@gmail.com',
     url='https://developer.mozilla.org/en-US/docs/Developer_Guide/mach',
-    packages=['mach', 'mach.mixin'],
+    packages=['mach'],
     version=VERSION,
     classifiers=[
         'Environment :: Console',
         'Development Status :: 3 - Alpha',
         'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
         'Natural Language :: English',
     ],
     install_requires=[
--- a/python/mach_commands.py
+++ b/python/mach_commands.py
@@ -25,18 +25,16 @@ from mozbuild.base import (
 )
 
 from mach.decorators import (
     CommandArgument,
     CommandProvider,
     Command,
 )
 
-here = os.path.abspath(os.path.dirname(__file__))
-
 
 @CommandProvider
 class MachCommands(MachCommandBase):
     @Command('python', category='devenv',
              description='Run Python.')
     @CommandArgument('--no-virtualenv', action='store_true',
                      help='Do not set up a virtualenv')
     @CommandArgument('args', nargs=argparse.REMAINDER)
@@ -62,20 +60,16 @@ class MachCommands(MachCommandBase):
                                 append_env=append_env)
 
     @Command('python-test', category='testing',
              description='Run Python unit tests with an appropriate test runner.')
     @CommandArgument('-v', '--verbose',
                      default=False,
                      action='store_true',
                      help='Verbose output.')
-    @CommandArgument('--three',
-                     default=False,
-                     action='store_true',
-                     help='Run tests using Python 3.')
     @CommandArgument('-j', '--jobs',
                      default=1,
                      type=int,
                      help='Number of concurrent jobs to run. Default is 1.')
     @CommandArgument('--subsuite',
                      default=None,
                      help=('Python subsuite to run. If not specified, all subsuites are run. '
                            'Use the string `default` to only run tests without a subsuite.'))
@@ -92,23 +86,18 @@ class MachCommands(MachCommandBase):
             mozfile.remove(tempdir)
 
     def run_python_tests(self,
                          tests=None,
                          test_objects=None,
                          subsuite=None,
                          verbose=False,
                          jobs=1,
-                         three=False,
                          **kwargs):
-        if three:
-            # use pipenv to run tests against Python 3
-            self.activate_pipenv(os.path.join(here, 'Pipfile'), ['--three'])
-        else:
-            self._activate_virtualenv()
+        self._activate_virtualenv()
 
         if test_objects is None:
             from moztest.resolve import TestResolver
             resolver = self._spawn(TestResolver)
             # If we were given test paths, try to find tests matching them.
             test_objects = resolver.resolve_tests(paths=tests, flavor='python')
         else:
             # We've received test_objects from |mach test|. We need to ignore
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -752,21 +752,21 @@ class MozbuildObject(ProcessExecutionMix
         self._activate_virtualenv()
         pipenv = os.path.join(self.virtualenv_manager.bin_path, 'pipenv')
         if not os.path.exists(pipenv):
             pipenv_reqs = os.path.join(self.topsrcdir, 'python/mozbuild/mozbuild/pipenv.txt')
             self.virtualenv_manager.install_pip_requirements(
                 pipenv_reqs, require_hashes=False, vendored=True)
         return pipenv
 
-    def activate_pipenv(self, path, args=None):
+    def activate_pipenv(self, path):
         if not os.path.exists(path):
             raise Exception('Pipfile not found: %s.' % path)
         self.ensure_pipenv()
-        self.virtualenv_manager.activate_pipenv(path, args)
+        self.virtualenv_manager.activate_pipenv(path)
 
 
 class MachCommandBase(MozbuildObject):
     """Base class for mach command providers that wish to be MozbuildObjects.
 
     This provides a level of indirection so MozbuildObject can be refactored
     without having to change everything that inherits from it.
     """
--- a/python/mozbuild/mozbuild/virtualenv.py
+++ b/python/mozbuild/mozbuild/virtualenv.py
@@ -528,29 +528,28 @@ class VirtualenvManager(object):
         # This will confuse pip and cause the package to attempt to install
         # against the executing interpreter. By creating a new process, we
         # force the virtualenv's interpreter to be used and all is well.
         # It /might/ be possible to cheat and set sys.executable to
         # self.python_path. However, this seems more risk than it's worth.
         subprocess.check_call([os.path.join(self.bin_path, 'pip')] + args,
             stderr=subprocess.STDOUT)
 
-    def activate_pipenv(self, pipfile, args=None):
+    def activate_pipenv(self, pipfile):
         """Install a Pipfile located at path and activate environment"""
         pipenv = os.path.join(self.bin_path, 'pipenv')
         env = os.environ.copy()
         env.update({
             'PIPENV_IGNORE_VIRTUALENVS': '1',
             'PIPENV_PIPFILE': pipfile,
             'WORKON_HOME': os.path.join(self.topobjdir, '_virtualenvs'),
         })
 
-        args = args or []
         subprocess.check_call(
-            [pipenv, 'install'] + args,
+            [pipenv, 'install', '--deploy'],
             stderr=subprocess.STDOUT,
             env=env)
 
         self.virtualenv_root = subprocess.check_output(
             [pipenv, '--venv'],
             stderr=subprocess.STDOUT,
             env=env).rstrip()
 
deleted file mode 100644
--- a/python/mozversioncontrol/setup.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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 absolute_import
-
-from setuptools import setup, find_packages
-
-VERSION = '0.1'
-
-setup(
-    author='Mozilla Foundation',
-    author_email='Mozilla Release Engineering',
-    name='mozversioncontrol',
-    description='Mozilla version control functionality',
-    license='MPL 2.0',
-    packages=find_packages(),
-    version=VERSION,
-    classifiers=[
-        'Development Status :: 3 - Alpha',
-        'Topic :: Software Development :: Build Tools',
-        'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: Implementation :: CPython',
-    ],
-    keywords='mozilla',
-)
--- a/testing/mozbase/mozrunner/setup.py
+++ b/testing/mozbase/mozrunner/setup.py
@@ -1,14 +1,15 @@
 # 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 absolute_import
 
+import sys
 from setuptools import setup, find_packages
 
 PACKAGE_NAME = 'mozrunner'
 PACKAGE_VERSION = '7.0.1'
 
 desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)"""
 
 deps = [
@@ -18,16 +19,18 @@ deps = [
     'mozlog==3.*',
     'mozprocess>=0.23,<1',
     'mozprofile>=1.1.0,<2',
     'six>=1.10.0,<2',
 ]
 
 EXTRAS_REQUIRE = {'crash': ['mozcrash >= 1.0']}
 
+# we only support python 2 right now
+assert sys.version_info[0] == 2
 
 setup(name=PACKAGE_NAME,
       version=PACKAGE_VERSION,
       description=desc,
       long_description="see https://firefox-source-docs.mozilla.org/mozbase/index.html",
       classifiers=['Environment :: Console',
                    'Intended Audience :: Developers',
                    'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
deleted file mode 100644
--- a/third_party/python/jsmin/LICENSE.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Dave St.Germain
-
-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.
-
-
deleted file mode 100644
--- a/third_party/python/jsmin/MANIFEST.in
+++ /dev/null
@@ -1,1 +0,0 @@
-include *.txt
deleted file mode 100644
--- a/third_party/python/jsmin/PKG-INFO
+++ /dev/null
@@ -1,92 +0,0 @@
-Metadata-Version: 1.1
-Name: jsmin
-Version: 2.0.11
-Summary: JavaScript minifier.
-PLEASE UPDATE TO VERSION >= 2.0.6. Older versions have a serious bug related to comments.
-Home-page: https://bitbucket.org/dcs/jsmin/
-Author: Tikitu de Jager
-Author-email: tikitu+jsmin@logophile.org
-License: MIT License
-Description: =====
-        jsmin
-        =====
-        
-        JavaScript minifier.
-        
-        Usage
-        =====
-        
-        .. code:: python
-        
-         from jsmin import jsmin
-         with open('myfile.js') as js_file:
-             minified = jsmin(js_file.read())
-        
-        You can run it as a commandline tool also::
-        
-          python -m jsmin myfile.js
-        
-        Where to get it
-        ===============
-        
-        * install the package `from pypi <https://pypi.python.org/pypi/jsmin/>`_
-        * get the latest release `from the stable branch on bitbucket <https://bitbucket.org/dcs/jsmin/branch/stable>`_
-        * get the development version `from the default branch on bitbucket <https://bitbucket.org/dcs/jsmin/branch/default>`_
-        
-        Contributing
-        ============
-        
-        `Issues <https://bitbucket.org/dcs/jsmin/issues>`_ and `Pull requests <https://bitbucket.org/dcs/jsmin/pull-requests>`_
-        will be gratefully received on Bitbucket. Pull requests on github are great too, but the issue tracker lives on
-        bitbucket.
-        
-        If possible, please make separate pull requests for tests and for code: tests will be committed on the stable branch
-        (which tracks the latest released version) while code will go to default by, erm, default.
-        
-        Unless you request otherwise, your Bitbucket identity will be added to the contributor's list below; if you prefer a
-        different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let
-        the maintainer know somehow.)
-        
-        Build/test status
-        =================
-        
-        Both default and stable branches are tested with Travis: https://travis-ci.org/tikitu/jsmin
-        
-        Stable (latest released version plus any new tests) is tested against CPython 2.6, 2.7, 3.2, and 3.3.
-        Currently:
-        
-        .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=ghstable
-        
-        If stable is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet
-        released.
-        
-        Default (development version, might be ahead of latest released version) is tested against CPython 2.6, 2.7, 3.2, and
-        3.3. Currently:
-        
-        .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master
-        
-        If default is failing don't use it, but as long as stable is passing the pypi release should be ok.
-        
-        Contributors (chronological commit order)
-        =========================================
-        
-        * `Dave St.Germain <https://bitbucket.org/dcs>`_ (original author)
-        * `Hans weltar <https://bitbucket.org/hansweltar>`_
-        * `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_ (current maintainer)
-        * https://bitbucket.org/rennat
-        
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Web Environment
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
-Classifier: Topic :: Software Development :: Pre-processors
-Classifier: Topic :: Text Processing :: Filters
deleted file mode 100644
--- a/third_party/python/jsmin/README.rst
+++ /dev/null
@@ -1,67 +0,0 @@
-=====
-jsmin
-=====
-
-JavaScript minifier.
-
-Usage
-=====
-
-.. code:: python
-
- from jsmin import jsmin
- with open('myfile.js') as js_file:
-     minified = jsmin(js_file.read())
-
-You can run it as a commandline tool also::
-
-  python -m jsmin myfile.js
-
-Where to get it
-===============
-
-* install the package `from pypi <https://pypi.python.org/pypi/jsmin/>`_
-* get the latest release `from the stable branch on bitbucket <https://bitbucket.org/dcs/jsmin/branch/stable>`_
-* get the development version `from the default branch on bitbucket <https://bitbucket.org/dcs/jsmin/branch/default>`_
-
-Contributing
-============
-
-`Issues <https://bitbucket.org/dcs/jsmin/issues>`_ and `Pull requests <https://bitbucket.org/dcs/jsmin/pull-requests>`_
-will be gratefully received on Bitbucket. Pull requests on github are great too, but the issue tracker lives on
-bitbucket.
-
-If possible, please make separate pull requests for tests and for code: tests will be committed on the stable branch
-(which tracks the latest released version) while code will go to default by, erm, default.
-
-Unless you request otherwise, your Bitbucket identity will be added to the contributor's list below; if you prefer a
-different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let
-the maintainer know somehow.)
-
-Build/test status
-=================
-
-Both default and stable branches are tested with Travis: https://travis-ci.org/tikitu/jsmin
-
-Stable (latest released version plus any new tests) is tested against CPython 2.6, 2.7, 3.2, and 3.3.
-Currently:
-
-.. image:: https://travis-ci.org/tikitu/jsmin.png?branch=ghstable
-
-If stable is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet
-released.
-
-Default (development version, might be ahead of latest released version) is tested against CPython 2.6, 2.7, 3.2, and
-3.3. Currently:
-
-.. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master
-
-If default is failing don't use it, but as long as stable is passing the pypi release should be ok.
-
-Contributors (chronological commit order)
-=========================================
-
-* `Dave St.Germain <https://bitbucket.org/dcs>`_ (original author)
-* `Hans weltar <https://bitbucket.org/hansweltar>`_
-* `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_ (current maintainer)
-* https://bitbucket.org/rennat
--- a/third_party/python/jsmin/jsmin/__init__.py
+++ b/third_party/python/jsmin/jsmin/__init__.py
@@ -35,44 +35,45 @@ else:
     except ImportError:
         cStringIO = None
 
 
 __all__ = ['jsmin', 'JavascriptMinify']
 __version__ = '2.0.11'
 
 
-def jsmin(js):
+def jsmin(js, **kwargs):
     """
     returns a minified version of the javascript string
     """
     if not is_3:        
         if cStringIO and not isinstance(js, unicode):
             # strings can use cStringIO for a 3x performance
             # improvement, but unicode (in python2) cannot
             klass = cStringIO.StringIO
         else:
             klass = StringIO.StringIO
     else:
         klass = io.StringIO
     ins = klass(js)
     outs = klass()
-    JavascriptMinify(ins, outs).minify()
+    JavascriptMinify(ins, outs, **kwargs).minify()
     return outs.getvalue()
 
 
 class JavascriptMinify(object):
     """
     Minify an input stream of javascript, writing
     to an output stream
     """
 
-    def __init__(self, instream=None, outstream=None):
+    def __init__(self, instream=None, outstream=None, quote_chars="'\""):
         self.ins = instream
         self.outs = outstream
+        self.quote_chars = quote_chars
 
     def minify(self, instream=None, outstream=None):
         if instream and outstream:
             self.ins, self.outs = instream, outstream
         
         self.is_return = False
         self.return_buf = ''
         
@@ -85,17 +86,17 @@ class JavascriptMinify(object):
             self.outs.write(char)
             if self.is_return:
                 self.return_buf = ''
 
         read = self.ins.read
 
         space_strings = "abcdefghijklmnopqrstuvwxyz"\
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$\\"
-        starters, enders = '{[(+-', '}])+-"\''
+        starters, enders = '{[(+-', '}])+-' + self.quote_chars
         newlinestart_strings = starters + space_strings
         newlineend_strings = enders + space_strings
         do_newline = False
         do_space = False
         escape_slash_count = 0
         doing_single_comment = False
         previous_before_comment = ''
         doing_multi_comment = False
@@ -115,17 +116,17 @@ class JavascriptMinify(object):
                 previous = next1
                 next1 = read(1)
             else:
                 in_re = True  # literal regex at start of script
                 write(previous)
         elif not previous:
             return
         elif previous >= '!':
-            if previous in "'\"":
+            if previous in self.quote_chars:
                 in_quote = previous
             write(previous)
             previous_non_space = previous
         else:
             previous_non_space = ' '
         if not next1:
             return
 
@@ -214,19 +215,19 @@ class JavascriptMinify(object):
                     write('/')
             else:
                 if do_space:
                     do_space = False
                     write(' ')
                 if do_newline:
                     write('\n')
                     do_newline = False
-                    
+
                 write(next1)
-                if not in_re and next1 in "'\"":
+                if not in_re and next1 in self.quote_chars:
                     in_quote = next1
                     quote_buf = []
 
             previous = next1
             next1 = next2
 
             if previous >= '!':
                 previous_non_space = previous
deleted file mode 100644
--- a/third_party/python/jsmin/jsmin/__main__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import sys, os, glob
-from jsmin import JavascriptMinify
-
-for f in sys.argv[1:]:
-    with open(f, 'r') as js:
-        minifier = JavascriptMinify(js, sys.stdout)
-        minifier.minify()
-    sys.stdout.write('\n')
-    
-    
--- a/third_party/python/jsmin/jsmin/test.py
+++ b/third_party/python/jsmin/jsmin/test.py
@@ -7,18 +7,18 @@ class JsTests(unittest.TestCase):
         return jsmin.jsmin(js)
 
     def assertEqual(self, thing1, thing2):
         if thing1 != thing2:
             print(repr(thing1), repr(thing2))
             raise AssertionError
         return True
     
-    def assertMinified(self, js_input, expected):
-        minified = jsmin.jsmin(js_input)
+    def assertMinified(self, js_input, expected, **kwargs):
+        minified = jsmin.jsmin(js_input, **kwargs)
         assert minified == expected, "%r != %r" % (minified, expected)
         
     def testQuoted(self):
         js = r'''
         Object.extend(String, {
           interpret: function(value) {
             return value == null ? '' : String(value);
           },
@@ -342,14 +342,53 @@ var  foo    =  "hey";
         expected = 'var msie;'
         self.assertMinified(original, expected)
 
     def test_angular_4(self):
         original = 'var /* comment */ msie;'
         expected = 'var msie;'
         self.assertMinified(original, expected)
 
-    def test_angular_4(self):
+    def test_angular_5(self):
         original = 'a/b'
         self.assertMinified(original, original)
 
+    def testBackticks(self):
+        original = '`test`'
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+        original = '` test with leading whitespace`'
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+        original = '`test with trailing whitespace `'
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+        original = '''`test
+with a new line`'''
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+        original = '''dumpAvStats: function(stats) {
+        var statsString = "";
+        if (stats.mozAvSyncDelay) {
+          statsString += `A/V sync: ${stats.mozAvSyncDelay} ms `;
+        }
+        if (stats.mozJitterBufferDelay) {
+          statsString += `Jitter-buffer delay: ${stats.mozJitterBufferDelay} ms`;
+        }
+
+        return React.DOM.div(null, statsString);'''
+        expected = 'dumpAvStats:function(stats){var statsString="";if(stats.mozAvSyncDelay){statsString+=`A/V sync: ${stats.mozAvSyncDelay} ms `;}\nif(stats.mozJitterBufferDelay){statsString+=`Jitter-buffer delay: ${stats.mozJitterBufferDelay} ms`;}\nreturn React.DOM.div(null,statsString);'
+        self.assertMinified(original, expected, quote_chars="'\"`")
+
+    def testBackticksExpressions(self):
+        original = '`Fifteen is ${a + b} and not ${2 * a + b}.`'
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+        original = '''`Fifteen is ${a +
+b} and not ${2 * a + "b"}.`'''
+        self.assertMinified(original, original, quote_chars="'\"`")
+
+    def testBackticksTagged(self):
+        original = 'tag`Hello ${ a + b } world ${ a * b}`;'
+        self.assertMinified(original, original, quote_chars="'\"`")
+
 if __name__ == '__main__':
     unittest.main()