Files
palemoon27/python/mach_commands.py
T
roytam1 7a3a0e6300 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 987225 - Combine the various tasks in Experiments.jsm to a single serial task. r=gfritzsche (delegated from felipe). Also fixes: (8120a07ce3)
- Bug 987207 - Telemetry experiments - Assure proper saving & loading from the cache. r=felipe (9cd601f3d8)
- Bug 983231 - Telemetry experiments: test manifest condition evaluation. r=felipe (c06e5fbe8a)
- Bug 988710 - Task.spawn can launch synchronously, which leads to a race setting and clearing this._mainTask. Move that into the .then() clause of _run. Also fix up some logging and FHR issues, r=gfritzsche (1fe4dc795e)
- Bug 973992 - Telemetry experiments: Make the experiments code use the new experiments addon type. r=Unfocused (ba8190caa6)
- Bug 986040 - Telemetry experiments: Assure that no experiment addon is running yet before starting an experiment. r=Unfocused (22564be0c8)
- Bug 985084 - Experiment add-ons should be disabled by default; r=Unfocused (f9ccaba1d0)
- Bug 986582 - Get rid of the toolkit.telemetry.enabledPreRelease pref and make the toolkit.telemetry.enabled pref do the right thing for beta users who are testing a final release build, r=rnewman (562b0c1b8f)
- Bug 989137 - Part 1: Uninstall unknown experiments; r=Unfocused (37cf1f6dd1)
- Bug 989137 - Part 2: Don't use a global logger; r=gfritzsche (c55dcb55c7)
- Bug 989137 - Part 4: Use a prefixing logger for Experiments logging; r=gfritzsche (cc9fbb31ae)
- Bug 985089 followup: fix mis-spelling of isNaN, r=gfritzsche (e221aee86d)
- Bug 989137 - Part 5: Prefix each log message with the instance of the object; r=gfritzsche (9e71983125)
- Bug 989137 - Part 8: Prevent unknown experiments from being installed; r=Unfocused (5268f362a7)
- Bug 989137 - Part 9: Ensure add-ons are enabled when they should be; r=Unfocused, r=gfritzsche (ebfe549767)
- Bug 989137 - Part 11: Make service initialization and uninitialization more robust; r=gfritzsche (07c74527a4)
- Bug 993084 attempt - make CommonUtils and Metrics imports lazy, since they aren't going to be needed anywhere near startup or when experiments is disabled, r=gps (d33224a8d8)
- Bug 993084 - Don't load experiments module if the feature is preffed off. r=bsmedberg (3ed2683663)
- Bug 993084 - Delay initialization of telemetry experiments if there is no active experiment. r=bsmedberg (7e2275159e)
- Bug 993084 - Fix experiments health report provider test. r=bsmedberg (0f898940c3)
- Bug 994727 - Telemetry experiments: Fix disabling the feature. r=bsmedberg (9f0ca445a1)
- Bug 989137 - Part 12: Refactor experiment and add-on state management. r=gfritzsche (49cc28671b)
- Bug 989137 - Part 13: Ability to ignore hashes of downloaded experiments. r=gfritzsche (8d92a1a105)
- Bug 989137 - Part 14: Rename functions for associating with Add-on Manager. r=gfritzsche (51d062f344)
- Bug 1007710 - Add information about the currently-active experiment to the telemetry ping, r=gfritzsche+vladan (66ae7184dc)
- Bug 989137 - Part 15: Return a promise from Experiments.init(). r=gfritzsche (b8ccc71c2a)
- Bug 989137 - Part 18: Fix experiments uninit behavior. r=bsmedberg (4466819dd3)
- Bug 995027 logging - add traces to figure out whether uninit was called and where it got stuck, r=gfritzsche (9f55a6780e)
- Bug 990111 - Add-on provider for historical experiments. r=irving (9042c27612)
- Bug 986677 - Add time left and activity state to experiments in the Addon Manager UI. r=unfocused (f39872aa16)
- Bug 1000719 - Add tracing on logging experiment rejections and telemetry tests. r=bsmedberg (a7ca202923)
- Bug 1001787 - Propagate changes for foreign experiment addon uninstalls so we properly save the experiments state. r=bsmedberg (6d88349ead)
- Bug 1001787 - Set the endDate on historic experiments early enough. r=bsmedberg (1a9312fca1)
- Bug 1004665 - If the crash reporter is disabled, .annotateCrashReport will throw an exception. Catch it and continue, r=gfritzsche (05d939a4a2)
- Bug 992258 - Trigger a refresh of the experiments view in the addon manager when experiments change. r=irving (de52a61c0a)
- Bug 1010289 - Experiments.jsm should now handle its errors. r=bsmedberg (991e948580)
- Bug 1005270 - Trigger experiments initialization on opening the addon manager UI. r=bsmedberg (7c3a7bfbbd)
- Bug 1021002 - Fix telemetry experiments jsfilter evaluation. r=bsmedberg (a2d52452d6)
- Bug 1028612 - Options for jsfilter sandbox unused. r=gfritzsche (5fac7b9b3e)
- Bug 1017806 - Record and report on optional branches of experiments, so that each experiment doesn't have to re-invent data collection. r=gfritzsche (d7fcb2e55a)
- Bug 1017806 followup: include the branch data in the public API and therefore in FHR (252968e1dd)
- Bug 1031326 - Fix experiment cache upgrade: the cache data is a raw JSObject, not a map. r=gfritzsche (f61a1fcdae)
- Bug 1027242 - Blacklist mulet's failing tests + expose 'mulet' to ini files; fix previous bustage on a CLOSED TREE, r=ahal (a88f7ef3ad)
- Bug 1012466 - Properly synchronize experiments shutdown with the AddonManager by using its shutdown barrier. r=bsmedberg (ffe92914e4)
- Bug 1259023 - if proxy is a nullpointer, do not set IS_PROXY in AccessibleOrProxy. r=tbsaunde (7c1059c45a)
- Bug 1012466 - Test cleanups. r=bsmedberg (26c00a6053)
- Bug 1032970 - Stopping maxStartTime from incorrectly disabling experiments which have already started. r=gfritzsche (816ef36335)
- Bug 1040761 - Re-add state info for experiments async shutdown blocker from bug 1012924. r=gfritzsche (91b6d99617)
- Bug 1046910 - TypeError: this._experiments is null at Experiments.Experiments.prototype._getState. r=ttaubert (80cc12df13)
- Bug 1048793 - Remove Experiments CertUtils usage as PublicKeyPinningService already provides the same functionality. r=mmc (221f2db6b3)
- Bug 1038174 - Prevent a race condition when writing the experiments cache. r=gfritzsche (cf05e977a6)
- Bug 1052545 - Telemetry experiment branches are not saved correctly: we set the _dirty flag correctly, but then don't write the cache, r=gfritzsche (74aab3d5e7)
- Bug 1012924 diagnostics - increase the log length to 10, r=gfritzsche (f08ff68ca4)
- Bug 1054397 - automated test for the racy while setting experiment branches, followup to bug 1052545 and bug 1038174, r=gfritzsche (2e715feb72)
- Bug 1012924 - Experiments should cancel their XMLHttpRequest on shutdown, and should also set a reasonable timeout on them, r=gfritzsche (0cfc12f1be)
- Bug 1064470 - Increase the experiments forensic log buffer size again. r=bsmedberg (5aaaf956f3)
- Bug 1059674 - use AsynchShutdown.blocker() for AddonManager provider shutdown; r=unfocused (113ee05270)
- Bug 1115040 - Record experiment branch in crash reports, r=gfritzsche (0a7def1f53)
- Bug 1123384 - Move Telemetry main ping implementation out of TelemetryPing.jsm. r=gfritzsche (1b19ce93c3)
- Bug 1087110 - Don't update experiments manifests if no experiment is running. r=gfritzsche (25cea68f2b)
- Bug 1139460 - Bonus: Remove unused function from experiments code. rs=yoric (19662893da)
- Bug 1151086 - Fix experiment filter functions to use the new telemetry environment, r=gfritzsche (de1ab33cd2)
- Bug 1192924: Expose the update URL formatting code a new UpdateUtils module. r=rstrong (8ff23b0c3d)
- Bug 1202902 - Mass replace toplevel 'let' with 'var' in preparation for global lexical scope. (1b3dd408d3)
- Bug 1207490 - Part 7: Remove use of expression closure from browser/experiments/. r=Gijs (74f961a4ae)
- Bug 1202902 - Fix the world. (9eef98d71a)
- Bug 1218266 - Harden against AsyncShutdown timeouts in Experiments.jsm. r=mossop (75bb3fb437)
- Bug 1228628 - Add a minimal .eslintrc configuration for browser and start linting a few browser files with basic rules. r=Mossop (bb3ab37ce4)
- Bug 1217282 - Experiments are enabled even when telemetry is disabled. r=gfritzsche (739a4e65ba)
- Bug 1233492 - make browser/experiments eslintable, r=felipe (820bd4f76e)
- Bug 1234490 - Remove the Experiments FHR provider. r=gps (21aab54c65)
- Bug 1245649: Turn on no-extra-semi. r=markh (67e49a3fd5)
- Bug 1245544 - Telemetry experiments aren't expiring historical data properly. r=gfritzsche (ffe330e3fa)
- Bug 1245544 - Fix the indentation in Experiments.jsm. r=gfritzsche (9a7d5c21de)
- Bug 1255745 - Make Experiments AsyncShutdown state data more useful. r=dexter (3a234295c1)
- Bug 1257246: Update browser for eslint 2. r=felipe (43eaff49db)
- bits of Bug 1042699: Block cross-origin add-on install requests. (9dee5b50e8)
- Bug 1239868 - remove unused PREF_EM_UPDATE_INTERVAL. r=Mossop (5bf01ede2d)
- Bug 1225944 - Allow reinstalling temp add-ons. r=Mossop (05770e0842)
- Bug 1180901 - Test that a locked file cannot be removed from the extensions trash directory on Windows r=mossop (276d413090)
- Bug 1180901 - Test that an extension can be installed when a locked file exists in the extensions trash directory as long as the extension being installed does not touch the locked file. r=mossop (0833b92bcf)
- Bug 1258858: Fix harmless console errors in test_webextension.js. r=aswan (efedc5e4cc)
- Bug 1262005 - Rework how WebExtensions IDs are determined. r=rhelmer (bcb9514807)
- Bug 1245956 - Don't distinguish preliminary signing for add-ons part 2 r=mossop (b9c5e5f668)
- Bug 667963 - Load distribution extensions for existing profiles; r=Mossop (4fc765415a)
- Bug 1252181 - switch browser_ext_runtime_setUninstallURL.js to temporary add-on install r=mossop (dd874b3887)
- Bug 1245376 - do not advertise updates for locked install locations r=mossop (5203c173be)
- Bug 1265447 - Silence startup JavaScript strict warning in resource://gre/modules/addons/XPIProvider.jsm. r=rhelmer (961838062b)
- Bug 1263271 - Avoid startup JavaScript strict warning in resource://gre/modules/addons/XPIProvider.jsm. r=Mossop (c1183130ea)
- Bug 1178456 - Experiments service shouldn't use FHR prefs. r=gfritzsche (055833238b)
- Bug 1234526 - Remove unused healthreporter prefs. r=gfritzsche (0b67d4ef57)
- Bug 1263804 - Remove last references to Metrics.jsm. r=gijs (75ae2faa5d)
- Bug 989137 - Part 6: Create experiment XPIs during the build; r=bsmedberg (c61c53a2de)
- Bug 1098135 - Convert some rules to misc tier; r=glandium (9c32e22577)
- bits of Bug 1235676 - Replace $(abspath $(DEPTH)) with $(topobjdir). (fa75701e7b)
- Bug 1258019 - avoid JS errors on closed windows in ContentWebRTC.jsm, r=felipe. (f5891d5f8f)
- Bug 1240164 - Avoid caching tab dimensions in taskbar preview init code. Improves sessionrestore by about 1.5%. r=Dao (fae543ed65)
- Bug 1255450 - [mach] Replace ConfigProvider class with config_settings attribute, r=gps (13c90559ad)
- Bug 1255196 - Include mozinfo.json in common.tests.zip; r=gps (f8e90acb9d)
- Bug 1119365 - Implement |mach ide| for mobile/android and IntelliJ/Android Studio. r=nalexander (a5cd944260)
- Bug 1193914 - Properly check ide type when deciding whether or not to package. r=benwa (74f6d12e56)
- Bug 1176642 - Defer import Eclipse backend modules; r=glandium (bec7bef0f4)
- Bug 1230848 - Remove Gradle configuration rooted in the object directory. r=gps (595ff01dc2)
- Bug 1261412 - Report when mach python-test collects no tests; r=gps (dcb9462653)
- Bug 1261412 - Add mach python-test option to collect tests based on path alone; r=gps (76e2114900)
- Bug 1261412 - Relax test output requirement in mach python-test; r=gps (28f3fefa67)
- Bug 1262978: Run npm to get the path to installed binaries if eslint can't otherwise be found. r=gps (e74a12f884)
- Bug 1261456 - Combine support-files listed in [DEFAULT] with any listed per-test rather than overriding. r=gps (50320a54a0)
- Bug 1263188 - fix event tree cutting, part1, r=yzen (eeda83e65f)
- Bug 1263188 - fix event tree building, part2, r=yzen (20854e1566)
- Bug 1259023 - fixing invalid array index assertion when accessing next sibling. r=tbsaunde (9f153b2298)
- bug 1262980 - expose the table interface on proxies r=dbolter (edf50d4a0c)
- Bug 1241752 - Remove runtime warning for nsIContent::GetEditingHost(). r=smaug (b5f2f30cda)
2024-06-05 09:28:44 +08:00

381 lines
14 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 with an appropriate test runner.')
@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('--path-only',
default=False,
action='store_true',
help=('Collect all tests under given path instead of default '
'test resolution. Supports pytest-style tests.'))
@CommandArgument('tests', nargs='*',
metavar='TEST',
help=('Tests to run. Each test can be a single file or a directory. '
'Default test resolution relies on PYTHON_UNIT_TESTS.'))
def python_test(self,
tests=[],
test_objects=None,
subsuite=None,
verbose=False,
path_only=False,
stop=False):
self._activate_virtualenv()
def find_tests_by_path():
import glob
files = []
for t in tests:
if t.endswith('.py') and os.path.isfile(t):
files.append(t)
elif os.path.isdir(t):
for root, _, _ in os.walk(t):
files += glob.glob(mozpath.join(root, 'test*.py'))
files += glob.glob(mozpath.join(root, 'unit*.py'))
else:
self.log(logging.WARN, 'python-test',
{'test': t},
'TEST-UNEXPECTED-FAIL | Invalid test: {test}')
if stop:
break
return files
# 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. Most tests are run via mozunit,
# which produces output in the format Mozilla infrastructure expects.
# Some tests are run via pytest, and these should be equipped with a
# local mozunit_report plugin to meet output expectations.
return_code = 0
found_tests = False
if test_objects is None:
# If we're not being called from `mach test`, do our own
# test resolution.
if path_only:
if tests:
self.virtualenv_manager.install_pip_package(
'pytest==2.9.1'
)
test_objects = [{'path': p} for p in find_tests_by_path()]
else:
self.log(logging.WARN, 'python-test', {},
'TEST-UNEXPECTED-FAIL | No tests specified')
test_objects = []
else:
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 everything in PYTHON_UNIT_TESTS
test_objects = resolver.resolve_tests(flavor='python')
for test in test_objects:
found_tests = True
f = test['path']
file_displayed_test = [] # Used as a boolean.
def _line_handler(line):
if not file_displayed_test:
output = ('Ran' in line or 'collected' in line or
line.startswith('TEST-'))
if output:
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
if not found_tests:
message = 'TEST-UNEXPECTED-FAIL | No tests collected'
if not path_only:
message += ' (Not in PYTHON_UNIT_TESTS? Try --path-only?)'
self.log(logging.WARN, 'python-test', {}, message)
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:
npmPath = self.getNodeOrNpmPath("npm")
if npmPath:
try:
output = subprocess.check_output([npmPath, "bin", "-g"],
stderr=subprocess.STDOUT)
if minversion:
base = output.split("\n").strip()
binary = os.path.join(base, "eslint")
if not os.path.is_file(binary):
binary = None
except (subprocess.CalledProcessError, WindowsError):
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