Files
palemoon27/python/mach_commands.py
T
roytam1 58d1cd1df0 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1299615 - Part 2: Skip ICU source directory in Clang build plugin when searching for implicit conversion constructors. r=Waldo, r=mystor (30a51b6602)
- Bug 1264827 - Part 1: Rename the existing code to make it clear it's checking for template args; r=mystor (2710d7e318)
- Bug 1264827 - Part 2: Add a static analysis to help check Rust wrapped C++ classes for members which are unsafe to memmove; r=mystor (8f053f59cf)
- Bug 1264827 - Part 3: Add the MOZ_NEEDS_MEMMOVABLE_MEMBERS annotation to MFBT; r=froydnj (937622926a)
- Bug 1229769 - We should be able to use DOM promises in the worker debugger;r=khuey (b3b32e9b94)
- Bug 1265035 - Make ~WorkerJSRuntime() handle Initialize() failure better. r=khuey. (67e67fab06)
- Bug 1256428 P1 Add ServiceWorkerJob2 base class. r=jdm (0bedbfa070)
- Bug 1256428 P2 Add ServiceWorkerJobQueue2 class. r=jdm (806e9b242e)
- Bug 1260933 - Part 1: For invalid easing values, print the invalid value. r=birtles (482541cfcb)
- Bug 1260933 - Part 2: For invalid duration values, print the invalid value. r=birtles (5b20918f77)
- Bug 1256428 P3 Add ServiceWorkerUpdateJob2. r=jdm (135e9bf05d)
- Bug 1256428 P4 Add ServiceWorkerRegisterJob2. r=jdm (e790f95b1d)
- Bug 1256428 P5 Add ServiceWorkerUnregisterJob2 class. r=jdm (cf63826b57)
- Bug 1220757 - Add report to console when service worker register fails due to mismatching scope path.r=bkelly (dbbf1a8515)
- Bug 1255621 - Ignore service workers previously registered in non-private windows. r=bkelly (593ebfc612)
- Bug 1241531 - Part 1: Only pop jobs from the queue when the correct job completes. r=ehsan (f8a1ea2fda)
- Bug 1241531 - Part 2: Move Cancel() to ServiceWorkerJob base class. r=ehsan (33ffccb8a4)
- Bug 1241531 - Part 3: Call Cancel() on all service worker jobs. r=ehsan (4cce06ab41)
- Bug 1241531 - Part 4: Make service worker unregister job respect cancelation. r=ehsan (1877cb3919)
- Bug 1261776 Use SafeElementAt() in service worker job queue. r=ehsan (c7a883a087)
- Bug 1238990 P1 ServiceWorkerManager should trigger automatic updates in current process. r=ehsan (c65bded060)
- Bug 1238990 P2 Try to ensure service worker jobs do not run during shutdown. r=ehsan (f816a012f2)
- Bug 1256428 P6 Use ServiceWorkerJobQueue2 and new job classes in ServiceWorkerManager. r=jdm (641af03802)
- Bug 1256428 P0 Fix unified build failures in dom/workers. r=jdm (33aaafd188)
- Bug 1261814: Use the presence of the content global, and not any random global, to determine whether to run the close handler. r=bz (8f182bf345)
- Bug 1256428 P7 Fix wpt update.https.html to expect TypeError per current spec. r=jdm (4c6cad6e0f)
- Bug 1256428 P8 Fix wpt unregister-then-register-new-script.https.html to new spec expectations matching blink's tests. r=jdm (d9191f7002)
- Bug 1226443 P5 Always use first scheduled update timer instead of rescheduling on new events. r=ehsan (7b1b31dcc0)
- Bug 1230341 Hold a strong ref in service worker NS_NewRunnableMethodWithArg uses. r=ehsan a=abillings (2b1d942ae4)
- Bug 1256428 P9 Remove now unused code from ServiceWorkerManager.cpp. r=jdm (7f97035007)
- Bug 1256428 P10 Remove ServiceWorkerRegistrationInfo::mUpdating flag. r=jdm (31fc686d5d)
- Bug 1256428 P11 Don't coalesce SW jobs after the existing job has already resolved its promise. r=jdm (1ce373f98b)
- Bug 1256428 P12 ServiceWorkerUnregisterJob2 should not use ServiceWorkerManager internals. r=jdm (1abe304c3c)
- Bug 1256428 P13 Remove unnecessary ServiceWorkerUnregsterJob2 stop. r=jdm (05d0717b7c)
- Bug 1256428 P14 Remove dead code in SeviceWorkerUpdateJob.cpp. r=jdm (7d1ac1112a)
- Bug 1256428 P15 Perform byte-for-byte comparison check after validating script URL. r=jdm (dc30ec75a9)
- Bug 1256428 P16 Fix some issues calling purgeCache() in ServiceWorkerUpdateJob.cpp. r=jdm (cffe93613a)
- Bug 1256428 P17 Rename service worker job classes to remove "2" suffix. r=jdm (f1d7a6aadf)
- Bug 1256428 P18 Add spec annotations and tweak asserts in ServiceWorkerUpdateJob. r=jdm (1a9c95a5bb)
- Bug 1256428 P19 Address ServiceWorkerUnregisterJob review feedback. r=jdm (2b8775a9ad)
- Bug 1260591 Move ServiceWorkerInfo and ServiceWorkerRegistrationInfo into separate files. r=jdm (2e31a3c002)
- Bug 1266857 Make Clients.claim() use observer document list instead of secondary hashtable. r=bz (2b318072f5)
- Bug 1261428: Migrate the useless setTimeout error message to the bindings infrastructure. r=bz (80d2503978)
- Bug 1263307 P1 Make ServiceWorkerRegistrationInfo::mScope const. r=jdm (b8b03bc594)
- Bug 1263307 P2 Make ServiceWorkerRegistrationInfo worker members private. r=jdm (16773a9134)
- Bug 1263307 P3 Move ServiceWorker update logic into central place in ServiceWorkerRegistrationInfo methods. r=jdm (68b288cbfb)
- Bug 1265761 Clients.matchAll() should treat http windows as secure if devtools are open and http testing is enabled. r=ehsan (100e16ca08)
- Bug 1265795 P1 Uncontrolled service workers when global is removed from document. r=bz (db069b0756)
- Bug 1265795 P2 Add a web-platform-test for the window navigation case. r=bz (6571257e5b)
- Bug 1265795 P3 Assert that controlled documents have an outer window. r=bz (fdc14dbf66)
- Bug 1265795 P4 Always call nsDocument::SetScriptGlobalObject(nullptr) from nsDocument::Destroy(). r=bz (8825c3dbd5)
- Bug 1239349 - Implement webNavigation.onHistoryStateUpdated. r=kmag (94f41a3df1)
- Bug 1213993: [webext] Support frameId/allFrames/runAt in browser.tabs.executeScript and insertCSS. r=billm (ccb7ba2362)
- Bug 1246031 - Utility for obtaining platform information. r=kmag (daf9aa5cfd)
- Bug 1246754 - Complete the implementation of chrome.i18n.detectLanguage, r=kmag (fab69e3cfe)
- Bug 1217129: [webext] Follow-up: Fix race in pageAction tests. (3d957f8ef3)
- Bug 1217129 - ESLint fix r=me (892a32d5a6)
- Bug 1213450 - Complete the implementation of chrome.i18n - getAcceptLanguages, r=kmag (6432705857)
- Bug 1246029 Implement chrome.commands.onCommand. r=kmag (50d4f0d2d3)
- Bug 1248499: [webext] Implement tabs.detectLanguage. r=billm (d85e2f89ea)
- Bug 1220154, 1249830: Handle sendMessage replies with 0 and >1 listeners correctly. r=billm (64af469c10)
- Bug 1250784: Part 3 - [webext] Add suport for runtime.openOptionsPage. r=Mossop (a154bc04be)
- Bug 1217129: Part 6 - [webext] Test browserAction popups in both the toolbar and in the menu panel. r=gijs r=billm (a3631de42a)
- Bug 1190663: [webext] Add tests for window.close() in browserAction and pageAction popups. r=rpl (e9a8fe9ae7)
- Bug 1225633 - Add better default styles to WebExtension panels. ui-r=shorlander, r=kmag (e8ab0eb6d7)
- Bug 1248846: [webext] Don't call callbacks after a context is destroyed. r=aswan (059263d0aa)
- Bug 1247081: Support fragment IDs and query strings in web_accessible_resources URLs. r=billm (d436e58380)
- Bug 1217944 - Part 2 - Support wildcards in web_accessible_resources r=kmag (9cd5e7529e)
- Bug 1234755: Follow-up: Fix additional failures. r=trivial (c6b4e64a0d)
- Bug 1163862 - Switch to HTTP observer + support requestId & data: URIs + test fixes r=billm (b9613edc8c)
- Bug 1234020: Part 2c - [webext] Return promises from the idle API. r=rpl (0eb719013b)
- Bug 1223634 - Support exclude_globs/include_globs in webext manifests. r=kmag (c1cb88dad3)
- Bug 1232849 - Better chrome compatibility + binaryValue support + serious header manipulation tests + nits r=kmag (87ab4ee657)
- Bug 1253924 - Implement statusLine + fix & test statusCode r=kmag (af62b946e2)
- Bug 1256264 - Make requestId a string. r=kmag (7caaf40411)
- Bug 1252596 - Implement webRequest.onErrorOccurred. r=kmag (6a6d2f0a77)
- Bug 1242871 - add an originUrl property to every webRequest event details object + tests (extended & fixed + nits). r=kmag (3e5be00ed9)
- Bug 1223634 - fix eslint failure. r=me (3f8d7230f8)
- Bug 1217944 - Part 1 - Make MatchGlobs work on arbitrary strings r=kmag (8af0926ede)
- Bug 1264623 - Allow for a leading slash in the path to web_accessible_resources, r=kmag (cf747f9d9e)
- Bug 1196283: [webext] Support comments in JSON files. r=aswan (4018b251d8)
- Bug 1256282 - [webext] Fix addonId checks in getAPILevelForWindow and add an xpcshell test unit. r=kmag (05347f47eb)
- Bug 1204575 - fix WebExtension EventManager fireFunc registering. r=billm r=gabor (229a69aef2)
- Bug 1251892: Fix EventManager cleanup code. r=rpl (535e518ee9)
- Bug 1248846: [webext] Test that event callbacks and promises do not fire later than expected. r=aswan (015e467224)
- Bug 1260888 - Enable the extension xpcshell tests on Android. r=nalexander (3c08d8827d)
- Bug 1245597 - implement the basics of chrome.downloads.download(). r=kmag (6a83e0a757)
- Bug 1245603 - Implement browser.downloads.search(). r=kmag (cf9a2163de)
- Bug 1245600 - Implement chrome.downloads.onChanged for state. r=kmag (fea9180b21)
- Bug 1251766 - Accept more date formats for downloads.search(). r=kmag (60dba788e8)
- Bug 1245599 - Implement chrome.downloads.onCreated r=kmag (c16b76b88c)
- Bug 1253565 - [webext] Run event pages as background pages and log warning on persistent manifest attribute. r=kmag (be811aeac1)
- Bug 1245640 - Implement chrome.downloads.showDefaultDirectory() r=kmag (9afde72e3d)
- Bug 1245602 - Implement chrome.downloads.pause(), .resume(), .cancel() r=kmag (c1054b637c)
- Bug 1253565 - [webext] test "UnrecognizedProperty" on content_scripts manifest properties. r=kmag (99f560ecdf)
- Bug 1005193 - Allow addons to specify a custom global debug context. r=mossop (4a7f89d893)
- Bug 1239884: Part 1 - [webext] Don't create an extra API context for background pages. r=billm (367db1fcb4)
- Bug 1197346 - Rename ExtensionPage to ExtensionContext (r=kmag) (8072e5eb80)
- Bug 1214955: [webext] Automatically localize all localizable manifest properties. r=billm (13a70b733d)
- Bug 1243602 - don't expose browser.* properties that lack required permissions. r=kmag (a6bf62149b)
- Bug 1197346 - Add callFunctionNoReturn (r=kmag) (3b52af77c9)
- Bug 1258139: Part 1 - [webext] Refactor storage API code. r=rpl (bed8bcb20c)
- Bug 1258139: Part 2 - [webext] Fix dead wrapper issues in storage API. r=gabor (a24e2dfa66)
- Bug 1197346 - Allow browser.storage to be used from content scripts (r=kmag) (aae63c8805)
- Bug 1251766 - Add new Date type to webextensions schemas. r=kmag (f6ca6a11a7)
- Bug 1254194: [webext] Allow extensions to register custom content security policies. r=billm f=aswan (2247892a40)
- Bug 1254194: Add a validator for custom add-on content security policies. r=billm f=aswan (c557dd47ef)
- Bug 1254194: Allow iterating over and inspecting sources of parsed CSP directives. r=ckerschb (2d93cdda56)
- Bug 1142332 - Prevent calling CSP_EnumToKeyword with CSP_HASH. r=ckerschb (15a80ed62f)
- Bug 1236416 - Remove some misc toolkit content UI from Fennec r=margaret (01f7f81c93)
- Bug 1234403 - Part 1: Implement CSSPseudoElement.getAnimations. r=birtles (91ce2e1cae)
- Bug 1234403 - Part 2: Implement document.getAnimations. r=birtles (49afbacadb)
- Bug 1234403 - Part 3: Test for the CSSPseudoElement objects returned by effect.target. r=birtles (bf34dda38f)
- Bug 1234403 - Part 4: Test for the animation order returned by document.getAnimations(). r=birtles (fa8ec8e01f)
- Bug 1234403 - Part 5: Test for CSSPseudoElement.getAnimations. r=birtles (3ef598f2ba)
- Bug 1254418 - Part 1: Support generated-content element for Element.getAnimations. r=birtles (7ae806859a)
- Bug 1254418 - Part 2: Test getAnimations for generated-content elements. r=birtles (b562ec7478)
- Bug 1254761 - Part 1: Implement getAnimations({ subtree: true }). r=smaug (c5419ffec0)
- Bug 1254761 - Part 2: Removes extra whitespaces. r=birtles (2a98381928)
- Bug 1254761 - Part 3: Add tests for AnimationFilter. r=birtles (bdd9b39849)
- Bug 1254194: Apply a content security policy to all WebExtension documents. r=gabor (c3a9f32be8)
- Bug 1257246: Update the version of eslint that mach installs. r=gps (da0481d7e4)
- Bug 1229588: Add a taskcluster test for eslint. r=dustin (e6eff5caf2)
- Bug 1257246: Update lint test image to newer packages of eslint. r=ahal (bcfaf3b5d8)
- Bug 1263637 - Fix eslint 2 warnings for WebExtensions code. r=kmag (16537b22dc)
- Bug 1254194: [webext] Add 'onError' schema option to make manifest errors non-fatal. r=aswan (8525d8f192)
- Bug 1254194: [webext] Fix tests that violate the default CSP. r=aswan (daa3d59c10)
- Bug 1254194: [webext] Test that content security policies are applied to WebExtension documents. r=aswan (18d164132c)
- Bug 1261857 - [webext] Support WebExtensions ContentScripts in the Tab DevTools Debugger. r=kmag (bc8c97b49e)
- Bug 1258199: [webext] Return an empty string for missing keys in getMessage. r=aswan (651ba7bb76)
- Bug 1238177 - fix extension content needs to use the correct user context id origin attribute. r=sicking (834faa0f62)
- Bug 1257246: Update webextension APIs for eslint 2. r=kmag (bcc7a6bc69)
- Bug 1227462 - tabs.create and tabs.update should check URLs using checkLoadURL. r=kmag (d2de203430)
- Bug 1251289 - Fix chrome.i18n.getAcceptLanguages to *not* replace dashes with underscores in language codes. r=kmag (abe1a46745)
- Bug 1254947 - Fix instanceof checks that assume `promiseFromSomeGlobal instanceof otherGlobal.Promise` succeeds. r=bz (20ea190932)
2024-05-02 15:26:10 +08:00

320 lines
12 KiB
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/.
from __future__ import absolute_import, print_function, unicode_literals
import argparse
import logging
import mozpack.path as mozpath
import os
import platform
import subprocess
import sys
import which
from distutils.version import LooseVersion
from mozbuild.base import (
MachCommandBase,
)
from mach.decorators import (
CommandArgument,
CommandProvider,
Command,
)
ESLINT_NOT_FOUND_MESSAGE = '''
Could not find eslint! We looked at the --binary option, at the ESLINT
environment variable, and then at your path. Install eslint and needed plugins
with
mach eslint --setup
and try again.
'''.strip()
NODE_NOT_FOUND_MESSAGE = '''
nodejs v4.2.3 is either not installed or is installed to a non-standard path.
Please install nodejs from https://nodejs.org and try again.
Valid installation paths:
'''.strip()
NPM_NOT_FOUND_MESSAGE = '''
Node Package Manager (npm) is either not installed or installed to a
non-standard path. Please install npm from https://nodejs.org (it comes as an
option in the node installation) and try again.
Valid installation paths:
'''.strip()
@CommandProvider
class MachCommands(MachCommandBase):
@Command('python', category='devenv',
description='Run Python.')
@CommandArgument('args', nargs=argparse.REMAINDER)
def python(self, args):
# Avoid logging the command
self.log_manager.terminal_handler.setLevel(logging.CRITICAL)
self._activate_virtualenv()
return self.run_process([self.virtualenv_manager.python_path] + args,
pass_thru=True, # Allow user to run Python interactively.
ensure_exit_code=False, # Don't throw on non-zero exit code.
# Note: subprocess requires native strings in os.environ on Windows
append_env={b'PYTHONDONTWRITEBYTECODE': str('1')})
@Command('python-test', category='testing',
description='Run Python unit tests.')
@CommandArgument('--verbose',
default=False,
action='store_true',
help='Verbose output.')
@CommandArgument('--stop',
default=False,
action='store_true',
help='Stop running tests after the first error or failure.')
@CommandArgument('tests', nargs='*',
metavar='TEST',
help='Tests to run. Each test can be a single file or a directory.')
def python_test(self,
tests=[],
test_objects=None,
subsuite=None,
verbose=False,
stop=False):
self._activate_virtualenv()
# Python's unittest, and in particular discover, has problems with
# clashing namespaces when importing multiple test modules. What follows
# is a simple way to keep environments separate, at the price of
# launching Python multiple times. This also runs tests via mozunit,
# which produces output in the format Mozilla infrastructure expects.
return_code = 0
if test_objects is None:
# If we're not being called from `mach test`, do our own
# test resolution.
from mozbuild.testing import TestResolver
resolver = self._spawn(TestResolver)
if tests:
# If we were given test paths, try to find tests matching them.
test_objects = resolver.resolve_tests(paths=tests,
flavor='python')
else:
# Otherwise just run all Python tests.
test_objects = resolver.resolve_tests(flavor='python')
for test in test_objects:
f = test['path']
file_displayed_test = [] # Used as a boolean.
def _line_handler(line):
if not file_displayed_test and line.startswith('TEST-'):
file_displayed_test.append(True)
inner_return_code = self.run_process(
[self.virtualenv_manager.python_path, f],
ensure_exit_code=False, # Don't throw on non-zero exit code.
log_name='python-test',
# subprocess requires native strings in os.environ on Windows
append_env={b'PYTHONDONTWRITEBYTECODE': str('1')},
line_handler=_line_handler)
return_code += inner_return_code
if not file_displayed_test:
self.log(logging.WARN, 'python-test', {'file': f},
'TEST-UNEXPECTED-FAIL | No test output (missing mozunit.main() call?): {file}')
if verbose:
if inner_return_code != 0:
self.log(logging.INFO, 'python-test', {'file': f},
'Test failed: {file}')
else:
self.log(logging.INFO, 'python-test', {'file': f},
'Test passed: {file}')
if stop and return_code > 0:
return 1
return 0 if return_code == 0 else 1
@Command('eslint', category='devenv',
description='Run eslint or help configure eslint for optimal development.')
@CommandArgument('-s', '--setup', default=False, action='store_true',
help='configure eslint for optimal development.')
@CommandArgument('-e', '--ext', default='[.js,.jsm,.jsx,.xml,.html]',
help='Filename extensions to lint, default: "[.js,.jsm,.jsx,.xml,.html]".')
@CommandArgument('-b', '--binary', default=None,
help='Path to eslint binary.')
@CommandArgument('args', nargs=argparse.REMAINDER) # Passed through to eslint.
def eslint(self, setup, ext=None, binary=None, args=None):
'''Run eslint.'''
# eslint requires at least node 4.2.3
nodePath = self.getNodeOrNpmPath("node", LooseVersion("4.2.3"))
if not nodePath:
return 1
if setup:
return self.eslint_setup()
if not binary:
binary = os.environ.get('ESLINT', None)
if not binary:
try:
binary = which.which('eslint')
except which.WhichError:
pass
if not binary:
print(ESLINT_NOT_FOUND_MESSAGE)
return 1
self.log(logging.INFO, 'eslint', {'binary': binary, 'args': args},
'Running {binary}')
args = args or ['.']
cmd_args = [binary,
# Enable the HTML plugin.
# We can't currently enable this in the global config file
# because it has bad interactions with the SublimeText
# ESLint plugin (bug 1229874).
'--plugin', 'html',
'--ext', ext, # This keeps ext as a single argument.
] + args
success = self.run_process(cmd_args,
pass_thru=True, # Allow user to run eslint interactively.
ensure_exit_code=False, # Don't throw on non-zero exit code.
require_unix_environment=True # eslint is not a valid Win32 binary.
)
self.log(logging.INFO, 'eslint', {'msg': ('No errors' if success == 0 else 'Errors')},
'Finished eslint. {msg} encountered.')
return success
def eslint_setup(self, update_only=False):
"""Ensure eslint is optimally configured.
This command will inspect your eslint configuration and
guide you through an interactive wizard helping you configure
eslint for optimal use on Mozilla projects.
"""
sys.path.append(os.path.dirname(__file__))
npmPath = self.getNodeOrNpmPath("npm")
if not npmPath:
return 1
# Install eslint 1.10.3.
# Note that that's the version currently compatible with the mozilla
# eslint plugin.
success = self.callProcess("eslint",
[npmPath, "install", "eslint@2.8.0", "-g"])
if not success:
return 1
# Install eslint-plugin-mozilla.
success = self.callProcess("eslint-plugin-mozilla",
[npmPath, "link"],
"testing/eslint-plugin-mozilla")
if not success:
return 1
# Install eslint-plugin-html.
success = self.callProcess("eslint-plugin-html",
[npmPath, "install", "eslint-plugin-html@1.4.0", "-g"])
if not success:
return 1
# Install eslint-plugin-react.
success = self.callProcess("eslint-plugin-react",
[npmPath, "install", "eslint-plugin-react@4.2.3", "-g"])
if not success:
return 1
print("\nESLint and approved plugins installed successfully!")
def callProcess(self, name, cmd, cwd=None):
print("\nInstalling %s using \"%s\"..." % (name, " ".join(cmd)))
try:
with open(os.devnull, "w") as fnull:
subprocess.check_call(cmd, cwd=cwd, stdout=fnull)
except subprocess.CalledProcessError:
if cwd:
print("\nError installing %s in the %s folder, aborting." % (name, cwd))
else:
print("\nError installing %s, aborting." % name)
return False
return True
def getPossibleNodePathsWin(self):
"""
Return possible nodejs paths on Windows.
"""
if platform.system() != "Windows":
return []
return list({
"%s\\nodejs" % os.environ.get("SystemDrive"),
os.path.join(os.environ.get("ProgramFiles"), "nodejs"),
os.path.join(os.environ.get("PROGRAMW6432"), "nodejs"),
os.path.join(os.environ.get("PROGRAMFILES"), "nodejs")
})
def getNodeOrNpmPath(self, filename, minversion=None):
"""
Return the nodejs or npm path.
"""
if platform.system() == "Windows":
for ext in [".cmd", ".exe", ""]:
try:
nodeOrNpmPath = which.which(filename + ext,
path=self.getPossibleNodePathsWin())
if self.is_valid(nodeOrNpmPath, minversion):
return nodeOrNpmPath
except which.WhichError:
pass
else:
try:
nodeOrNpmPath = which.which(filename)
if self.is_valid(nodeOrNpmPath, minversion):
return nodeOrNpmPath
except which.WhichError:
pass
if filename == "node":
print(NODE_NOT_FOUND_MESSAGE)
elif filename == "npm":
print(NPM_NOT_FOUND_MESSAGE)
if platform.system() == "Windows":
appPaths = self.getPossibleNodePathsWin()
for p in appPaths:
print(" - %s" % p)
elif platform.system() == "Darwin":
print(" - /usr/local/bin/node")
elif platform.system() == "Linux":
print(" - /usr/bin/nodejs")
return None
def is_valid(self, path, minversion = None):
try:
version_str = subprocess.check_output([path, "--version"],
stderr=subprocess.STDOUT)
if minversion:
# nodejs prefixes its version strings with "v"
version = LooseVersion(version_str.lstrip('v'))
return version >= minversion
return True
except (subprocess.CalledProcessError, WindowsError):
return False