# HG changeset patch # User Andrew Halberstadt # Date 1532467306 0 # Node ID 2062a23f0e5a52cfe93ca4abef4da455cadf742a # Parent 10ca77b99e386ea556b9766f06647e8cb3e1cb5f Bug 1472177 - Run mozversioncontrol tests under python 3 r=gps This also enables the py2 linter which will help maintain compatibility with both 2 and 3. Differential Revision: https://phabricator.services.mozilla.com/D1884 diff --git a/python/mozversioncontrol/mozversioncontrol/__init__.py b/python/mozversioncontrol/mozversioncontrol/__init__.py --- a/python/mozversioncontrol/mozversioncontrol/__init__.py +++ b/python/mozversioncontrol/mozversioncontrol/__init__.py @@ -4,18 +4,18 @@ from __future__ import absolute_import, print_function, unicode_literals import abc import errno import os import re import subprocess -import which +from distutils.spawn import find_executable from distutils.version import LooseVersion class MissingVCSTool(Exception): """Represents a failure to find a version control tool binary.""" class MissingVCSInfo(Exception): @@ -43,32 +43,22 @@ class MissingUpstreamRepo(Exception): """Represents a failure to automatically detect an upstream repo.""" def get_tool_path(tool): """Obtain the path of `tool`.""" if os.path.isabs(tool) and os.path.exists(tool): return tool - # We use subprocess in places, which expects a Win32 executable or - # batch script. On some versions of MozillaBuild, we have "hg.exe", - # "hg.bat," and "hg" (a Python script). "which" will happily return the - # Python script, which will cause subprocess to choke. Explicitly favor - # the Windows version over the plain script. - try: - return which.which(tool + '.exe') - except which.WhichError: - try: - return which.which(tool) - except which.WhichError: - pass - - raise MissingVCSTool('Unable to obtain %s path. Try running ' - '|mach bootstrap| to ensure your environment is up to ' - 'date.' % tool) + path = find_executable(tool) + if not path: + raise MissingVCSTool('Unable to obtain %s path. Try running ' + '|mach bootstrap| to ensure your environment is up to ' + 'date.' % tool) + return path class Repository(object): """A class wrapping utility methods around version control repositories. This class is abstract and never instantiated. Obtain an instance by calling a ``get_repository_*()`` helper function. @@ -93,17 +83,18 @@ class Repository(object): def _run(self, *args, **runargs): return_codes = runargs.get('return_codes', []) cmd = (self._tool,) + args try: return subprocess.check_output(cmd, cwd=self.path, - env=self._env) + env=self._env, + universal_newlines=True) except subprocess.CalledProcessError as e: if e.returncode in return_codes: return '' raise @property def tool_version(self): '''Return the version of the VCS tool in use as a `LooseVersion`.''' @@ -258,17 +249,20 @@ class HgRepository(Repository): return self def __exit__(self, exc_type, exc_val, exc_tb): self._client.close() def _run(self, *args, **runargs): if not self._client.server: return super(HgRepository, self)._run(*args, **runargs) - return self._client.rawcommand(args) + + # hglib requires bytes on python 3 + args = [a.encode('utf-8') if not isinstance(a, bytes) else a for a in args] + return self._client.rawcommand(args).decode('utf-8') def sparse_checkout_present(self): # We assume a sparse checkout is enabled if the .hg/sparse file # has data. Strictly speaking, we should look for a requirement in # .hg/requires. But since the requirement is still experimental # as of Mercurial 4.3, it's probably more trouble than its worth # to verify it. sparse = os.path.join(self.path, '.hg', 'sparse') diff --git a/python/mozversioncontrol/mozversioncontrol/repoupdate.py b/python/mozversioncontrol/mozversioncontrol/repoupdate.py --- a/python/mozversioncontrol/mozversioncontrol/repoupdate.py +++ b/python/mozversioncontrol/mozversioncontrol/repoupdate.py @@ -1,13 +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 unicode_literals +from __future__ import absolute_import, unicode_literals import os import subprocess # The logic here is far from robust. Improvements are welcome. def update_mercurial_repo(hg, repo, path, revision='default', diff --git a/python/mozversioncontrol/setup.py b/python/mozversioncontrol/setup.py --- a/python/mozversioncontrol/setup.py +++ b/python/mozversioncontrol/setup.py @@ -15,13 +15,16 @@ setup( 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', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: Implementation :: CPython', ], keywords='mozilla', ) diff --git a/python/mozversioncontrol/test/python.ini b/python/mozversioncontrol/test/python.ini --- a/python/mozversioncontrol/test/python.ini +++ b/python/mozversioncontrol/test/python.ini @@ -1,7 +1,6 @@ [DEFAULT] subsuite=mozversioncontrol -skip-if = python == 3 [test_context_manager.py] [test_workdir_outgoing.py] [test_working_directory.py] diff --git a/tools/lint/py2.yml b/tools/lint/py2.yml --- a/tools/lint/py2.yml +++ b/tools/lint/py2.yml @@ -24,17 +24,16 @@ py2: - modules - mozglue - netwerk - nsprpub - other-licenses - python/devtools - python/mach - python/mozbuild - - python/mozversioncontrol - security - servo - testing/awsy - testing/firefox-ui - testing/geckodriver - testing/gtest - testing/mochitest - testing/mozharness