diff --git a/PRESUBMIT.py b/PRESUBMIT.py index cbfc6f66812d72..fcd302a44f0e7d 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -298,6 +298,17 @@ ) +_ANDROID_SPECIFIC_PYDEPS_FILES = [ + 'build/android/test_runner.pydeps', +] + +_GENERIC_PYDEPS_FILES = [ + 'build/secondary/tools/swarming_client/isolate.pydeps', +] + +_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES + + def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api): """Attempts to prevent use of functions intended only for testing in non-testing code. For now this is just a best-effort implementation @@ -1498,6 +1509,108 @@ def _CheckAndroidNewMdpiAssetLocation(input_api, output_api): return results +class PydepsChecker(object): + def __init__(self, input_api, pydeps_files): + self._file_cache = {} + self._input_api = input_api + self._pydeps_files = pydeps_files + + def _LoadFile(self, path): + """Returns the list of paths within a .pydeps file relative to //.""" + if path not in self._file_cache: + with open(path) as f: + self._file_cache[path] = f.read() + return self._file_cache[path] + + def _ComputeNormalizedPydepsEntries(self, pydeps_path): + """Returns an interable of paths within the .pydep, relativized to //.""" + os_path = self._input_api.os_path + pydeps_dir = os_path.dirname(pydeps_path) + entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines() + if not l.startswith('*')) + return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries) + + def _CreateFilesToPydepsMap(self): + """Returns a map of local_path -> list_of_pydeps.""" + ret = {} + for pydep_local_path in self._pydeps_files: + for path in self._ComputeNormalizedPydepsEntries(pydep_local_path): + ret.setdefault(path, []).append(pydep_local_path) + return ret + + def ComputeAffectedPydeps(self): + """Returns an iterable of .pydeps files that might need regenerating.""" + affected_pydeps = set() + file_to_pydeps_map = None + for f in self._input_api.AffectedFiles(include_deletes=True): + local_path = f.LocalPath() + if local_path == 'DEPS': + return self._pydeps_files + elif local_path.endswith('.pydeps'): + if local_path in self._pydeps_files: + affected_pydeps.add(local_path) + elif local_path.endswith('.py'): + if file_to_pydeps_map is None: + file_to_pydeps_map = self._CreateFilesToPydepsMap() + affected_pydeps.update(file_to_pydeps_map.get(local_path, ())) + return affected_pydeps + + def DetermineIfStale(self, pydeps_path): + """Runs print_python_deps.py to see if the files is stale.""" + old_pydeps_data = self._LoadFile(pydeps_path) + + m = self._input_api.re.search(r'# target: //(.*)', old_pydeps_data) + if not m: + return ['COULD NOT FIND .pydeps TARGET'] + target = m.group(1) + m = self._input_api.re.search(r'# root: //(.*)', old_pydeps_data) + if not m: + return ['COULD NOT FIND .pydeps ROOT'] + root = m.group(1) or '.' + + cmd = ['build/print_python_deps.py', '--root', root, target] + new_pydeps_data = self._input_api.subprocess.check_output(cmd) + if old_pydeps_data != new_pydeps_data: + return cmd[:-1] + ['--output', pydeps_path] + cmd[-1:] + + +def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None): + """Checks if a .pydeps file needs to be regenerated.""" + # TODO(agrieve): Update when there's a better way to detect this: crbug/570091 + is_android = input_api.os_path.exists('third_party/android_tools') + pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES + results = [] + # First, check for new / deleted .pydeps. + for f in input_api.AffectedFiles(include_deletes=True): + if f.LocalPath().endswith('.pydeps'): + if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES: + results.append(output_api.PresubmitError( + 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to ' + 'remove %s' % f.LocalPath())) + elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES: + results.append(output_api.PresubmitError( + 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to ' + 'include %s' % f.LocalPath())) + + if results: + return results + + checker = checker_for_tests or PydepsChecker(input_api, pydeps_files) + + for pydep_path in checker.ComputeAffectedPydeps(): + try: + cmd = checker.DetermineIfStale(pydep_path) + if cmd: + results.append(output_api.PresubmitError( + 'File is stale: %s\nTo regenerate, run:\n%s' % (pydep_path, + ' '.join(cmd)))) + except input_api.subprocess.CalledProcessError as error: + return [output_api.PresubmitError('Error running ' + ' '.join(error.cmd), + long_text=error.output)] + + return results + + def _CheckForCopyrightedCode(input_api, output_api): """Verifies that newly added code doesn't contain copyrighted material and is properly licensed under the standard Chromium license. @@ -1651,6 +1764,7 @@ def _AndroidSpecificOnUploadChecks(input_api, output_api): results.extend(_CheckAndroidCrLogUsage(input_api, output_api)) results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api)) results.extend(_CheckAndroidToastUsage(input_api, output_api)) + results.extend(_CheckPydepsNeedsUpdating(input_api, output_api)) return results diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index 90a8dafd07a3fe..4c688beab07152 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py @@ -3,12 +3,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import glob -import json -import os import re import subprocess -import sys import unittest import PRESUBMIT @@ -836,6 +832,103 @@ def testUserMetricsActionNotAddedToActions(self): output[0].message) +class PydepsNeedsUpdatingTest(unittest.TestCase): + + class MockSubprocess(object): + CalledProcessError = subprocess.CalledProcessError + + def setUp(self): + mock_all_pydeps = ['A.pydeps', 'B.pydeps'] + self.old_ALL_PYDEPS_FILES = PRESUBMIT._ALL_PYDEPS_FILES + PRESUBMIT._ALL_PYDEPS_FILES = mock_all_pydeps + self.mock_input_api = MockInputApi() + self.mock_output_api = MockOutputApi() + self.mock_input_api.subprocess = PydepsNeedsUpdatingTest.MockSubprocess() + self.checker = PRESUBMIT.PydepsChecker(self.mock_input_api, mock_all_pydeps) + self.checker._file_cache = { + 'A.pydeps': '# target: //A.py\n# root: //\nA.py\nC.py\n', + 'B.pydeps': '# target: //B.py\n# root: //\nB.py\nC.py\n', + } + + def tearDown(self): + PRESUBMIT._ALL_PYDEPS_FILES = self.old_ALL_PYDEPS_FILES + + def _RunCheck(self): + return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api, + self.mock_output_api, + checker_for_tests=self.checker) + + def testAddedPydep(self): + self.mock_input_api.files = [ + MockAffectedFile('new.pydeps', [], action='A'), + ] + + results = self._RunCheck() + self.assertEqual(1, len(results)) + self.assertTrue('PYDEPS_FILES' in str(results[0])) + + def testRemovedPydep(self): + self.mock_input_api.files = [ + MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0], [], action='D'), + ] + + results = self._RunCheck() + self.assertEqual(1, len(results)) + self.assertTrue('PYDEPS_FILES' in str(results[0])) + + def testRandomPyIgnored(self): + self.mock_input_api.files = [ + MockAffectedFile('random.py', []), + ] + + results = self._RunCheck() + self.assertEqual(0, len(results), 'Unexpected results: %r' % results) + + def testRelevantPyNoChange(self): + self.mock_input_api.files = [ + MockAffectedFile('A.py', []), + ] + + def mock_check_output(cmd): + self.assertEqual('A.py', cmd[3]) + return self.checker._file_cache['A.pydeps'] + + self.mock_input_api.subprocess.check_output = mock_check_output + + results = self._RunCheck() + self.assertEqual(0, len(results), 'Unexpected results: %r' % results) + + def testRelevantPyOneChange(self): + self.mock_input_api.files = [ + MockAffectedFile('A.py', []), + ] + + def mock_check_output(cmd): + self.assertEqual('A.py', cmd[3]) + return 'changed data' + + self.mock_input_api.subprocess.check_output = mock_check_output + + results = self._RunCheck() + self.assertEqual(1, len(results)) + self.assertTrue('File is stale' in str(results[0])) + + def testRelevantPyTwoChanges(self): + self.mock_input_api.files = [ + MockAffectedFile('C.py', []), + ] + + def mock_check_output(cmd): + return 'changed data' + + self.mock_input_api.subprocess.check_output = mock_check_output + + results = self._RunCheck() + self.assertEqual(2, len(results)) + self.assertTrue('File is stale' in str(results[0])) + self.assertTrue('File is stale' in str(results[1])) + + class LogUsageTest(unittest.TestCase): def testCheckAndroidCrLogUsage(self): diff --git a/PRESUBMIT_test_mocks.py b/PRESUBMIT_test_mocks.py index 5230c872107359..373b52c6d3c686 100644 --- a/PRESUBMIT_test_mocks.py +++ b/PRESUBMIT_test_mocks.py @@ -26,7 +26,7 @@ def __init__(self): self.is_committing = False self.change = MockChange([]) - def AffectedFiles(self, file_filter=None): + def AffectedFiles(self, file_filter=None, include_deletes=False): return self.files def AffectedSourceFiles(self, file_filter=None): @@ -92,13 +92,14 @@ class MockFile(object): MockInputApi for presubmit unittests. """ - def __init__(self, local_path, new_contents): + def __init__(self, local_path, new_contents, action='A'): self._local_path = local_path self._new_contents = new_contents self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)] + self._action = action def Action(self): - return 'A' # TODO(dbeam): feel free to change if your test actually uses. + return self._action def ChangedContents(self): return self._changed_contents diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index 73b25cde9299a7..af819ed3ce62c8 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn @@ -84,30 +84,25 @@ action("cpplib_stripped") { ] } -group("devil_py") { - data = [ - "devil_chromium.json", - "devil_chromium.py", - "//third_party/android_tools/sdk/build-tools/23.0.1/aapt", - "//third_party/android_tools/sdk/build-tools/23.0.1/dexdump", - "//third_party/android_tools/sdk/build-tools/23.0.1/lib/libc++.so", - "//third_party/android_tools/sdk/build-tools/23.0.1/split-select", - "//third_party/android_tools/sdk/platform-tools/adb", - "//third_party/catapult/catapult_base/catapult_base/", - "//third_party/catapult/dependency_manager/dependency_manager/", - "//third_party/catapult/third_party/gsutil/", - "//third_party/catapult/devil/devil/", - ] -} - group("test_runner_py") { - data = [ - "test_runner.py", - "pylib/", - "//build/util/lib/common/", - ] + _py_files = read_file("test_runner.pydeps", "list lines") + + # Filter out comments. + set_sources_assignment_filter([ "#*" ]) + sources = _py_files + + data = sources + [ + "devil_chromium.json", + "//third_party/android_tools/sdk/build-tools/23.0.1/aapt", + "//third_party/android_tools/sdk/build-tools/23.0.1/dexdump", + "//third_party/android_tools/sdk/build-tools/23.0.1/lib/libc++.so", + "//third_party/android_tools/sdk/build-tools/23.0.1/split-select", + "//third_party/android_tools/sdk/platform-tools/adb", + "//third_party/catapult/third_party/gsutil/", + "//third_party/catapult/devil/devil/devil_dependencies.json", + ] data_deps = [ - ":devil_py", + "//tools/swarming_client:isolate_py", ] } diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps new file mode 100644 index 00000000000000..1f4a559b8ec999 --- /dev/null +++ b/build/android/test_runner.pydeps @@ -0,0 +1,153 @@ +# Generated by //build/print_python_deps.py +# root: //build/android +# target: //build/android/test_runner.py +../../third_party/appurify-python/src/appurify/__init__.py +../../third_party/appurify-python/src/appurify/api.py +../../third_party/appurify-python/src/appurify/constants.py +../../third_party/appurify-python/src/appurify/utils.py +../../third_party/catapult/catapult_base/catapult_base/__init__.py +../../third_party/catapult/catapult_base/catapult_base/cloud_storage.py +../../third_party/catapult/catapult_base/catapult_base/util.py +../../third_party/catapult/dependency_manager/dependency_manager/__init__.py +../../third_party/catapult/dependency_manager/dependency_manager/archive_info.py +../../third_party/catapult/dependency_manager/dependency_manager/base_config.py +../../third_party/catapult/dependency_manager/dependency_manager/cloud_storage_info.py +../../third_party/catapult/dependency_manager/dependency_manager/dependency_info.py +../../third_party/catapult/dependency_manager/dependency_manager/dependency_manager_util.py +../../third_party/catapult/dependency_manager/dependency_manager/exceptions.py +../../third_party/catapult/dependency_manager/dependency_manager/local_path_info.py +../../third_party/catapult/dependency_manager/dependency_manager/manager.py +../../third_party/catapult/dependency_manager/dependency_manager/uploader.py +../../third_party/catapult/devil/devil/__init__.py +../../third_party/catapult/devil/devil/android/__init__.py +../../third_party/catapult/devil/devil/android/apk_helper.py +../../third_party/catapult/devil/devil/android/battery_utils.py +../../third_party/catapult/devil/devil/android/constants/__init__.py +../../third_party/catapult/devil/devil/android/constants/file_system.py +../../third_party/catapult/devil/devil/android/decorators.py +../../third_party/catapult/devil/devil/android/device_blacklist.py +../../third_party/catapult/devil/devil/android/device_errors.py +../../third_party/catapult/devil/devil/android/device_list.py +../../third_party/catapult/devil/devil/android/device_signal.py +../../third_party/catapult/devil/devil/android/device_temp_file.py +../../third_party/catapult/devil/devil/android/device_utils.py +../../third_party/catapult/devil/devil/android/flag_changer.py +../../third_party/catapult/devil/devil/android/forwarder.py +../../third_party/catapult/devil/devil/android/install_commands.py +../../third_party/catapult/devil/devil/android/logcat_monitor.py +../../third_party/catapult/devil/devil/android/md5sum.py +../../third_party/catapult/devil/devil/android/ports.py +../../third_party/catapult/devil/devil/android/sdk/__init__.py +../../third_party/catapult/devil/devil/android/sdk/aapt.py +../../third_party/catapult/devil/devil/android/sdk/adb_wrapper.py +../../third_party/catapult/devil/devil/android/sdk/build_tools.py +../../third_party/catapult/devil/devil/android/sdk/gce_adb_wrapper.py +../../third_party/catapult/devil/devil/android/sdk/intent.py +../../third_party/catapult/devil/devil/android/sdk/keyevent.py +../../third_party/catapult/devil/devil/android/sdk/split_select.py +../../third_party/catapult/devil/devil/android/sdk/version_codes.py +../../third_party/catapult/devil/devil/android/valgrind_tools/__init__.py +../../third_party/catapult/devil/devil/android/valgrind_tools/base_tool.py +../../third_party/catapult/devil/devil/base_error.py +../../third_party/catapult/devil/devil/constants/__init__.py +../../third_party/catapult/devil/devil/constants/exit_codes.py +../../third_party/catapult/devil/devil/devil_env.py +../../third_party/catapult/devil/devil/utils/__init__.py +../../third_party/catapult/devil/devil/utils/cmd_helper.py +../../third_party/catapult/devil/devil/utils/file_utils.py +../../third_party/catapult/devil/devil/utils/host_utils.py +../../third_party/catapult/devil/devil/utils/lazy/__init__.py +../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py +../../third_party/catapult/devil/devil/utils/parallelizer.py +../../third_party/catapult/devil/devil/utils/reraiser_thread.py +../../third_party/catapult/devil/devil/utils/run_tests_helper.py +../../third_party/catapult/devil/devil/utils/timeout_retry.py +../../third_party/catapult/devil/devil/utils/watchdog_timer.py +../../third_party/catapult/devil/devil/utils/zip_utils.py +../util/lib/common/perf_result_data_type.py +../util/lib/common/perf_tests_results_helper.py +../util/lib/common/unittest_util.py +devil_chromium.py +pylib/__init__.py +pylib/base/__init__.py +pylib/base/base_setup.py +pylib/base/base_test_result.py +pylib/base/base_test_runner.py +pylib/base/environment.py +pylib/base/environment_factory.py +pylib/base/test_collection.py +pylib/base/test_dispatcher.py +pylib/base/test_instance.py +pylib/base/test_instance_factory.py +pylib/base/test_run.py +pylib/base/test_run_factory.py +pylib/base/test_server.py +pylib/chrome_test_server_spawner.py +pylib/constants/__init__.py +pylib/constants/host_paths.py +pylib/gtest/__init__.py +pylib/gtest/gtest_test_instance.py +pylib/host_driven/__init__.py +pylib/host_driven/setup.py +pylib/host_driven/test_case.py +pylib/host_driven/test_info_collection.py +pylib/host_driven/test_runner.py +pylib/host_driven/tests_annotations.py +pylib/instrumentation/__init__.py +pylib/instrumentation/instrumentation_parser.py +pylib/instrumentation/instrumentation_test_instance.py +pylib/instrumentation/json_perf_parser.py +pylib/instrumentation/setup.py +pylib/instrumentation/test_jar.py +pylib/instrumentation/test_options.py +pylib/instrumentation/test_package.py +pylib/instrumentation/test_result.py +pylib/instrumentation/test_runner.py +pylib/junit/__init__.py +pylib/junit/setup.py +pylib/junit/test_dispatcher.py +pylib/junit/test_runner.py +pylib/linker/__init__.py +pylib/linker/setup.py +pylib/linker/test_case.py +pylib/linker/test_runner.py +pylib/local/__init__.py +pylib/local/device/__init__.py +pylib/local/device/local_device_environment.py +pylib/local/device/local_device_gtest_run.py +pylib/local/device/local_device_instrumentation_test_run.py +pylib/local/device/local_device_test_run.py +pylib/local/local_test_server_spawner.py +pylib/monkey/__init__.py +pylib/monkey/setup.py +pylib/monkey/test_options.py +pylib/monkey/test_runner.py +pylib/perf/__init__.py +pylib/perf/setup.py +pylib/perf/test_options.py +pylib/perf/test_runner.py +pylib/remote/__init__.py +pylib/remote/device/__init__.py +pylib/remote/device/appurify_constants.py +pylib/remote/device/appurify_sanitized.py +pylib/remote/device/remote_device_environment.py +pylib/remote/device/remote_device_gtest_run.py +pylib/remote/device/remote_device_helper.py +pylib/remote/device/remote_device_instrumentation_test_run.py +pylib/remote/device/remote_device_test_run.py +pylib/remote/device/remote_device_uirobot_test_run.py +pylib/results/__init__.py +pylib/results/flakiness_dashboard/__init__.py +pylib/results/flakiness_dashboard/json_results_generator.py +pylib/results/flakiness_dashboard/results_uploader.py +pylib/results/json_results.py +pylib/results/report_results.py +pylib/uirobot/__init__.py +pylib/uirobot/uirobot_test_instance.py +pylib/utils/__init__.py +pylib/utils/isolator.py +pylib/utils/proguard.py +pylib/utils/repo_utils.py +pylib/utils/test_environment.py +pylib/valgrind_tools.py +test_runner.py diff --git a/build/print_python_deps.py b/build/print_python_deps.py new file mode 100755 index 00000000000000..da83684dd21336 --- /dev/null +++ b/build/print_python_deps.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Prints all non-system dependencies for the given module. + +The primary use-case for this script is to genererate the list of python modules +required for .isolate files. +""" + +import argparse +import imp +import os +import pipes +import sys + +# Don't use any helper modules, or else they will end up in the results. + + +_SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) + + +def ComputePythonDependencies(root): + """Gets the paths of imported non-system python modules. + + A path is assumed to be a "system" import if it is outside of chromium's + src/. The paths will be relative to the current directory. + """ + module_paths = (m.__file__ for m in sys.modules.values() + if m and hasattr(m, '__file__')) + + src_paths = set() + for path in module_paths: + if path == __file__: + continue + path = os.path.abspath(path) + if not path.startswith(_SRC_ROOT): + continue + + if path.endswith('.pyc'): + path = path[:-1] + src_paths.add(os.path.relpath(path, root)) + + return sorted(src_paths) + + +def main(): + parser = argparse.ArgumentParser( + description='Prints all non-system dependencies for the given module.') + parser.add_argument('module', + help='The python module to analyze.') + parser.add_argument('--root', default='.', + help='Directory to make paths relative to.') + parser.add_argument('--output', + help='Write output to a file rather than stdout.') + options = parser.parse_args() + sys.path.append(os.path.dirname(options.module)) + imp.load_source('NAME', options.module) + out = open(options.output, 'w') if options.output else sys.stdout + with out: + out.write('# Generated by //build/print_python_deps.py\n') + out.write('# root: //%s\n' % os.path.relpath(options.root, _SRC_ROOT)) + out.write('# target: //%s\n' % os.path.relpath(options.module, _SRC_ROOT)) + for path in ComputePythonDependencies(options.root): + out.write(path + '\n') + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/build/secondary/tools/swarming_client/BUILD.gn b/build/secondary/tools/swarming_client/BUILD.gn new file mode 100644 index 00000000000000..f4860523c7c31d --- /dev/null +++ b/build/secondary/tools/swarming_client/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +group("isolate_py") { + _py_files = + read_file("//build/secondary/tools/swarming_client/isolate.pydeps", + "list lines") + + # Filter out comments. + set_sources_assignment_filter([ "#*" ]) + sources = _py_files + data = sources +} diff --git a/build/secondary/tools/swarming_client/isolate.pydeps b/build/secondary/tools/swarming_client/isolate.pydeps new file mode 100644 index 00000000000000..22af37b9371ce3 --- /dev/null +++ b/build/secondary/tools/swarming_client/isolate.pydeps @@ -0,0 +1,118 @@ +# Generated by //build/print_python_deps.py +# root: //tools/swarming_client +# target: //tools/swarming_client/isolate.py +auth.py +isolate.py +isolate_format.py +isolated_format.py +isolateserver.py +run_isolated.py +third_party/__init__.py +third_party/colorama/__init__.py +third_party/colorama/ansi.py +third_party/colorama/ansitowin32.py +third_party/colorama/initialise.py +third_party/colorama/win32.py +third_party/colorama/winterm.py +third_party/depot_tools/__init__.py +third_party/depot_tools/fix_encoding.py +third_party/depot_tools/subcommand.py +third_party/httplib2/__init__.py +third_party/httplib2/iri2uri.py +third_party/httplib2/socks.py +third_party/oauth2client/__init__.py +third_party/oauth2client/_helpers.py +third_party/oauth2client/_openssl_crypt.py +third_party/oauth2client/_pycrypto_crypt.py +third_party/oauth2client/client.py +third_party/oauth2client/clientsecrets.py +third_party/oauth2client/crypt.py +third_party/oauth2client/locked_file.py +third_party/oauth2client/multistore_file.py +third_party/oauth2client/util.py +third_party/pyasn1/pyasn1/__init__.py +third_party/pyasn1/pyasn1/codec/__init__.py +third_party/pyasn1/pyasn1/codec/ber/__init__.py +third_party/pyasn1/pyasn1/codec/ber/decoder.py +third_party/pyasn1/pyasn1/codec/ber/eoo.py +third_party/pyasn1/pyasn1/codec/cer/__init__.py +third_party/pyasn1/pyasn1/codec/cer/decoder.py +third_party/pyasn1/pyasn1/codec/der/__init__.py +third_party/pyasn1/pyasn1/codec/der/decoder.py +third_party/pyasn1/pyasn1/compat/__init__.py +third_party/pyasn1/pyasn1/compat/octets.py +third_party/pyasn1/pyasn1/debug.py +third_party/pyasn1/pyasn1/error.py +third_party/pyasn1/pyasn1/type/__init__.py +third_party/pyasn1/pyasn1/type/base.py +third_party/pyasn1/pyasn1/type/char.py +third_party/pyasn1/pyasn1/type/constraint.py +third_party/pyasn1/pyasn1/type/error.py +third_party/pyasn1/pyasn1/type/namedtype.py +third_party/pyasn1/pyasn1/type/namedval.py +third_party/pyasn1/pyasn1/type/tag.py +third_party/pyasn1/pyasn1/type/tagmap.py +third_party/pyasn1/pyasn1/type/univ.py +third_party/pyasn1/pyasn1/type/useful.py +third_party/requests/__init__.py +third_party/requests/adapters.py +third_party/requests/api.py +third_party/requests/auth.py +third_party/requests/certs.py +third_party/requests/compat.py +third_party/requests/cookies.py +third_party/requests/exceptions.py +third_party/requests/hooks.py +third_party/requests/models.py +third_party/requests/packages/__init__.py +third_party/requests/packages/urllib3/__init__.py +third_party/requests/packages/urllib3/_collections.py +third_party/requests/packages/urllib3/connection.py +third_party/requests/packages/urllib3/connectionpool.py +third_party/requests/packages/urllib3/contrib/__init__.py +third_party/requests/packages/urllib3/exceptions.py +third_party/requests/packages/urllib3/fields.py +third_party/requests/packages/urllib3/filepost.py +third_party/requests/packages/urllib3/packages/__init__.py +third_party/requests/packages/urllib3/packages/ordered_dict.py +third_party/requests/packages/urllib3/packages/six.py +third_party/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +third_party/requests/packages/urllib3/poolmanager.py +third_party/requests/packages/urllib3/request.py +third_party/requests/packages/urllib3/response.py +third_party/requests/packages/urllib3/util/__init__.py +third_party/requests/packages/urllib3/util/connection.py +third_party/requests/packages/urllib3/util/request.py +third_party/requests/packages/urllib3/util/response.py +third_party/requests/packages/urllib3/util/retry.py +third_party/requests/packages/urllib3/util/ssl_.py +third_party/requests/packages/urllib3/util/timeout.py +third_party/requests/packages/urllib3/util/url.py +third_party/requests/sessions.py +third_party/requests/status_codes.py +third_party/requests/structures.py +third_party/requests/utils.py +third_party/rsa/rsa/__init__.py +third_party/rsa/rsa/_compat.py +third_party/rsa/rsa/common.py +third_party/rsa/rsa/core.py +third_party/rsa/rsa/key.py +third_party/rsa/rsa/pem.py +third_party/rsa/rsa/pkcs1.py +third_party/rsa/rsa/prime.py +third_party/rsa/rsa/randnum.py +third_party/rsa/rsa/transform.py +third_party/rsa/rsa/varblock.py +third_party/six/__init__.py +utils/__init__.py +utils/file_path.py +utils/fs.py +utils/logging_utils.py +utils/lru.py +utils/net.py +utils/oauth.py +utils/on_error.py +utils/subprocess42.py +utils/threading_utils.py +utils/tools.py +utils/zip_package.py