libv8 6.7.288.46.1 → 7.3.492.27.0beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/CHANGELOG.md +4 -0
- data/README.md +2 -0
- data/ext/libv8/builder.rb +6 -2
- data/lib/libv8/version.rb +1 -1
- data/vendor/depot_tools/.gitattributes +1 -0
- data/vendor/depot_tools/.gitignore +7 -0
- data/vendor/depot_tools/CROS_OWNERS +5 -0
- data/vendor/depot_tools/OWNERS +12 -1
- data/vendor/depot_tools/PRESUBMIT.py +16 -9
- data/vendor/depot_tools/README.md +9 -2
- data/vendor/depot_tools/autoninja +14 -6
- data/vendor/depot_tools/autoninja.bat +11 -1
- data/vendor/depot_tools/autoninja.py +40 -18
- data/vendor/depot_tools/bb +12 -0
- data/vendor/depot_tools/bb.bat +7 -0
- data/vendor/depot_tools/bootstrap/win/manifest.txt +1 -1
- data/vendor/depot_tools/bootstrap/win/manifest_bleeding_edge.txt +1 -1
- data/vendor/depot_tools/bootstrap/win/win_tools.py +2 -1
- data/vendor/depot_tools/buildbucket.py +57 -4
- data/vendor/depot_tools/cipd +157 -44
- data/vendor/depot_tools/cipd.bat +51 -14
- data/vendor/depot_tools/cipd.ps1 +104 -42
- data/vendor/depot_tools/cipd_client_version +1 -1
- data/vendor/depot_tools/cipd_client_version.digests +21 -0
- data/vendor/depot_tools/cipd_manifest.txt +19 -6
- data/vendor/depot_tools/cipd_manifest.versions +318 -0
- data/vendor/depot_tools/clang_format.py +4 -4
- data/vendor/depot_tools/cpplint.py +44 -199
- data/vendor/depot_tools/dart_format.py +2 -2
- data/vendor/depot_tools/detect_host_arch.py +8 -3
- data/vendor/depot_tools/download_from_google_storage.py +47 -39
- data/vendor/depot_tools/fetch.py +30 -18
- data/vendor/depot_tools/fetch_configs/android_internal.py +34 -0
- data/vendor/depot_tools/fetch_configs/chromium.py +18 -1
- data/vendor/depot_tools/fetch_configs/config_util.py +4 -2
- data/vendor/depot_tools/fetch_configs/inspector_protocol.py +40 -0
- data/vendor/depot_tools/fetch_configs/node-ci.py +41 -0
- data/vendor/depot_tools/fix_encoding.py +3 -3
- data/vendor/depot_tools/gclient +1 -1
- data/vendor/depot_tools/gclient.py +415 -198
- data/vendor/depot_tools/gclient_eval.py +220 -171
- data/vendor/depot_tools/gclient_paths.py +142 -0
- data/vendor/depot_tools/gclient_scm.py +200 -51
- data/vendor/depot_tools/gclient_utils.py +88 -191
- data/vendor/depot_tools/gerrit_client.py +13 -0
- data/vendor/depot_tools/gerrit_util.py +158 -23
- data/vendor/depot_tools/git-nav-upstream +1 -1
- data/vendor/depot_tools/git_cache.py +77 -24
- data/vendor/depot_tools/git_cl.py +705 -1099
- data/vendor/depot_tools/git_common.py +9 -6
- data/vendor/depot_tools/git_map_branches.py +19 -2
- data/vendor/depot_tools/git_nav_downstream.py +3 -4
- data/vendor/depot_tools/git_rebase_update.py +14 -0
- data/vendor/depot_tools/git_reparent_branch.py +8 -2
- data/vendor/depot_tools/gn.py +38 -3
- data/vendor/depot_tools/gsutil.py +8 -3
- data/vendor/depot_tools/gsutil.py.bat +15 -0
- data/vendor/depot_tools/gsutil.vpython +16 -0
- data/vendor/depot_tools/infra/config/OWNERS +0 -1
- data/vendor/depot_tools/infra/config/recipes.cfg +3 -2
- data/vendor/depot_tools/lucicfg +12 -0
- data/vendor/depot_tools/lucicfg.bat +7 -0
- data/vendor/depot_tools/man/html/git-map-branches.html +34 -2
- data/vendor/depot_tools/man/html/git-new-branch.html +40 -32
- data/vendor/depot_tools/man/man1/git-map-branches.1 +24 -5
- data/vendor/depot_tools/man/man1/git-new-branch.1 +35 -27
- data/vendor/depot_tools/man/src/git-map-branches.demo.1.sh +1 -0
- data/vendor/depot_tools/man/src/git-map-branches.txt +10 -0
- data/vendor/depot_tools/man/src/git-new-branch.demo.1.sh +9 -4
- data/vendor/depot_tools/man/src/git-new-branch.txt +1 -1
- data/vendor/depot_tools/metrics.README.md +98 -0
- data/vendor/depot_tools/metrics.py +296 -0
- data/vendor/depot_tools/metrics_utils.py +303 -0
- data/vendor/depot_tools/my_activity.py +91 -29
- data/vendor/depot_tools/ninja +1 -1
- data/vendor/depot_tools/ninjalog.README.md +64 -0
- data/vendor/depot_tools/ninjalog_uploader.py +232 -0
- data/vendor/depot_tools/ninjalog_uploader_wrapper.py +116 -0
- data/vendor/depot_tools/owners.py +30 -13
- data/vendor/depot_tools/owners_finder.py +5 -2
- data/vendor/depot_tools/presubmit_canned_checks.py +188 -29
- data/vendor/depot_tools/presubmit_support.py +18 -41
- data/vendor/depot_tools/pylintrc +23 -19
- data/vendor/depot_tools/recipes/OWNERS +2 -0
- data/vendor/depot_tools/recipes/README.recipes.md +344 -151
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/OWNERS +2 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +2 -16
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +141 -99
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic.json +5 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_luci.json +5 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_with_branch_heads.json +6 -98
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/clobber.json +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +45 -5
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_rebase_patch_ref.json +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_reset.json +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{tryjob.json → input_commit_with_id_without_repo.json} +6 -11
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{tryjob_empty_revision.json → multiple_patch_refs.json} +8 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_apply_patch_on_gclient.json +19 -29
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{trychange.json → refs.json} +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/reset_root_solution_revision.json +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +51 -6
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +50 -6
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +51 -6
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle.json +17 -25
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_branch_heads.json +17 -25
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_feature_branch.json +18 -26
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8_feature_branch.json +18 -26
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_webrtc.json +26 -28
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +45 -5
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +17 -25
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/unrecognized_commit_repo.json +13 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_manifest_name.json +13 -152
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_tags.json +4 -9
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +185 -202
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +52 -157
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +5 -14
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/ensure_checkout.py +34 -0
- data/vendor/depot_tools/recipes/recipe_modules/cipd/api.py +14 -2
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic_pkg.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-failed.json +7 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-many-instances.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/mac64.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_file.json +9 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_mode.json +9 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_verfile.json +9 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/win64.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk arch.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk bits.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_32.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_64.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_32.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_64.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_mips_64.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/mac_intel_64.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_32.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_64.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/api.py +13 -8
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic.json +18 -12
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic_luci.json +18 -12
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/win.json +18 -12
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.py +3 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/__init__.py +1 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +58 -46
- data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +65 -22
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +20 -21
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/buildbot.json +20 -21
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +20 -21
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +20 -21
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +5 -2
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/patch_project.py +62 -14
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +24 -38
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +56 -50
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.py +15 -9
- data/vendor/depot_tools/recipes/recipe_modules/git/__init__.py +4 -1
- data/vendor/depot_tools/recipes/recipe_modules/git/api.py +34 -22
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_branch.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_file_name.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_hash.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_luci.json +222 -0
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_ref.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_submodule_update_force.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_tags.json +224 -0
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/can_fail_build.json +10 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cannot_fail_build.json +5 -7
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cat-file_test.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_delta.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_failed.json +5 -7
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output_fails_build.json +10 -5
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/curl_trace_file.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/git-cache-checkout.json +8 -9
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/platform_win.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/rebase_failed.json +12 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/remote_not_origin.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/set_got_revision.json +5 -6
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.py +27 -11
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/api.py +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.expected/basic.json +12 -13
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/__init__.py +5 -0
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/api.py +120 -5
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.expected/basic.json +45 -3
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.py +25 -0
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/resources/gerrit_client.py +56 -4
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.expected/basic.json +6 -0
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.py +49 -0
- data/vendor/depot_tools/recipes/recipe_modules/gsutil/api.py +24 -13
- data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.expected/basic.json +13 -14
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/basic.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_linux.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_mac.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_win.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_linux.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_mac.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_win.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_linux.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_mac.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_win.json +2 -3
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/path_config.py +1 -2
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/__init__.py +35 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/api.py +116 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/linux.json +22 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/mac.json +82 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/win.json +22 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.py +23 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/__init__.py +1 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/api.py +2 -7
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.expected/basic.json +7 -6
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +1 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +117 -8
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/basic_tags.json +4 -5
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/set_failure_hash_with_no_steps.json +7 -4
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch.json +98 -7
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch_and_target_ref.json +147 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_git_patch.json +8 -5
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_git_patch_luci.json +8 -5
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +9 -6
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch_new.json +9 -6
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +27 -2
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/test_api.py +14 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/__init__.py +25 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/api.py +137 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json +22 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json +22 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json +107 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.py +26 -0
- data/vendor/depot_tools/recipes/recipes.py +37 -27
- data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.expected/basic.json +7 -10
- data/vendor/depot_tools/repo +34 -8
- data/vendor/depot_tools/roll_dep.py +52 -49
- data/vendor/depot_tools/scm.py +38 -23
- data/vendor/depot_tools/setup_color.py +4 -2
- data/vendor/depot_tools/split_cl.py +32 -4
- data/vendor/depot_tools/subprocess2.py +22 -4
- data/vendor/depot_tools/third_party/httplib2/README.chromium +2 -2
- data/vendor/depot_tools/third_party/httplib2/__init__.py +242 -158
- data/vendor/depot_tools/third_party/httplib2/cacerts.txt +57 -44
- data/vendor/depot_tools/third_party/httplib2/socks.py +15 -5
- data/vendor/depot_tools/third_party/logilab/README.chromium +2 -4
- data/vendor/depot_tools/third_party/logilab/astroid/README.chromium +2 -1
- data/vendor/depot_tools/third_party/logilab/astroid/__init__.py +10 -5
- data/vendor/depot_tools/third_party/logilab/astroid/__pkginfo__.py +5 -5
- data/vendor/depot_tools/third_party/logilab/astroid/arguments.py +233 -0
- data/vendor/depot_tools/third_party/logilab/astroid/as_string.py +82 -33
- data/vendor/depot_tools/third_party/logilab/astroid/bases.py +137 -153
- data/vendor/depot_tools/third_party/logilab/astroid/brain/{builtin_inference.py → brain_builtin_inference.py} +117 -26
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_dateutil.py +15 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/{py2gi.py → brain_gi.py} +48 -8
- data/vendor/depot_tools/third_party/logilab/astroid/brain/{py2mechanize.py → brain_mechanize.py} +0 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/{pynose.py → brain_nose.py} +4 -1
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_numpy.py +62 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_pytest.py +76 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_qt.py +44 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/{pysix_moves.py → brain_six.py} +28 -1
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_ssl.py +65 -0
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_stdlib.py +473 -0
- data/vendor/depot_tools/third_party/logilab/astroid/builder.py +104 -81
- data/vendor/depot_tools/third_party/logilab/astroid/context.py +81 -0
- data/vendor/depot_tools/third_party/logilab/astroid/decorators.py +75 -0
- data/vendor/depot_tools/third_party/logilab/astroid/exceptions.py +20 -0
- data/vendor/depot_tools/third_party/logilab/astroid/inference.py +137 -183
- data/vendor/depot_tools/third_party/logilab/astroid/manager.py +45 -169
- data/vendor/depot_tools/third_party/logilab/astroid/mixins.py +37 -14
- data/vendor/depot_tools/third_party/logilab/astroid/modutils.py +112 -41
- data/vendor/depot_tools/third_party/logilab/astroid/node_classes.py +243 -156
- data/vendor/depot_tools/third_party/logilab/astroid/nodes.py +35 -22
- data/vendor/depot_tools/third_party/logilab/astroid/objects.py +186 -0
- data/vendor/depot_tools/third_party/logilab/astroid/protocols.py +157 -102
- data/vendor/depot_tools/third_party/logilab/astroid/raw_building.py +32 -8
- data/vendor/depot_tools/third_party/logilab/astroid/rebuilder.py +372 -309
- data/vendor/depot_tools/third_party/logilab/astroid/scoped_nodes.py +652 -420
- data/vendor/depot_tools/third_party/logilab/astroid/test_utils.py +4 -21
- data/vendor/depot_tools/third_party/logilab/astroid/transforms.py +96 -0
- data/vendor/depot_tools/third_party/logilab/astroid/util.py +89 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/LICENSE +19 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/README.chromium +11 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/__init__.py +20 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/cext.c +1421 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/compat.py +9 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/simple.py +246 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/slots.py +414 -0
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/utils.py +13 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/LICENSE +24 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/README.chromium +11 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/__init__.py +19 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/_wrappers.c +2729 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/arguments.py +96 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/decorators.py +512 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/importer.py +228 -0
- data/vendor/depot_tools/third_party/logilab/wrapt/wrappers.py +901 -0
- data/vendor/depot_tools/third_party/pylint/README.chromium +2 -25
- data/vendor/depot_tools/third_party/pylint/__pkginfo__.py +13 -3
- data/vendor/depot_tools/third_party/pylint/checkers/__init__.py +1 -2
- data/vendor/depot_tools/third_party/pylint/checkers/async.py +82 -0
- data/vendor/depot_tools/third_party/pylint/checkers/base.py +893 -119
- data/vendor/depot_tools/third_party/pylint/checkers/classes.py +342 -204
- data/vendor/depot_tools/third_party/pylint/checkers/design_analysis.py +51 -34
- data/vendor/depot_tools/third_party/pylint/checkers/exceptions.py +84 -47
- data/vendor/depot_tools/third_party/pylint/checkers/format.py +55 -30
- data/vendor/depot_tools/third_party/pylint/checkers/imports.py +314 -73
- data/vendor/depot_tools/third_party/pylint/checkers/logging.py +10 -8
- data/vendor/depot_tools/third_party/pylint/checkers/misc.py +2 -1
- data/vendor/depot_tools/third_party/pylint/checkers/newstyle.py +45 -48
- data/vendor/depot_tools/third_party/pylint/checkers/python3.py +31 -21
- data/vendor/depot_tools/third_party/pylint/checkers/raw_metrics.py +3 -3
- data/vendor/depot_tools/third_party/pylint/checkers/similar.py +4 -5
- data/vendor/depot_tools/third_party/pylint/checkers/spelling.py +24 -10
- data/vendor/depot_tools/third_party/pylint/checkers/stdlib.py +120 -56
- data/vendor/depot_tools/third_party/pylint/checkers/strings.py +38 -35
- data/vendor/depot_tools/third_party/pylint/checkers/typecheck.py +485 -138
- data/vendor/depot_tools/third_party/pylint/checkers/utils.py +319 -142
- data/vendor/depot_tools/third_party/pylint/checkers/variables.py +329 -207
- data/vendor/depot_tools/third_party/pylint/config.py +739 -76
- data/vendor/depot_tools/third_party/pylint/epylint.py +9 -5
- data/vendor/depot_tools/third_party/pylint/extensions/__init__.py +0 -0
- data/vendor/depot_tools/third_party/pylint/extensions/check_docs.py +311 -0
- data/vendor/depot_tools/third_party/pylint/extensions/check_elif.py +62 -0
- data/vendor/depot_tools/third_party/{logilab/common → pylint}/graph.py +30 -133
- data/vendor/depot_tools/third_party/pylint/gui.py +2 -2
- data/vendor/depot_tools/third_party/pylint/interfaces.py +21 -3
- data/vendor/depot_tools/third_party/pylint/lint.py +123 -140
- data/vendor/depot_tools/third_party/pylint/pyreverse/diadefslib.py +10 -13
- data/vendor/depot_tools/third_party/pylint/pyreverse/diagrams.py +15 -4
- data/vendor/depot_tools/third_party/pylint/pyreverse/inspector.py +372 -0
- data/vendor/depot_tools/third_party/pylint/pyreverse/main.py +30 -7
- data/vendor/depot_tools/third_party/pylint/pyreverse/utils.py +80 -2
- data/vendor/depot_tools/third_party/{logilab/common → pylint/pyreverse}/vcgutils.py +19 -37
- data/vendor/depot_tools/third_party/pylint/pyreverse/writer.py +3 -4
- data/vendor/depot_tools/third_party/pylint/reporters/__init__.py +34 -18
- data/vendor/depot_tools/third_party/pylint/reporters/guireporter.py +1 -1
- data/vendor/depot_tools/third_party/pylint/reporters/html.py +10 -3
- data/vendor/depot_tools/third_party/pylint/reporters/json.py +10 -4
- data/vendor/depot_tools/third_party/pylint/reporters/text.py +94 -3
- data/vendor/depot_tools/third_party/pylint/reporters/ureports/__init__.py +106 -0
- data/vendor/depot_tools/third_party/{logilab/common → pylint/reporters}/ureports/html_writer.py +17 -57
- data/vendor/depot_tools/third_party/{logilab/common → pylint/reporters}/ureports/nodes.py +52 -74
- data/vendor/depot_tools/third_party/{logilab/common → pylint/reporters}/ureports/text_writer.py +14 -60
- data/vendor/depot_tools/third_party/pylint/testutils.py +22 -20
- data/vendor/depot_tools/third_party/pylint/utils.py +268 -44
- data/vendor/depot_tools/third_party/repo/progress.py +42 -0
- data/vendor/depot_tools/update_depot_tools +1 -1
- data/vendor/depot_tools/upload_metrics.py +25 -0
- data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +45 -15
- data/vendor/depot_tools/win_toolchain/package_from_installed.py +71 -24
- data/vendor/depot_tools/yapf +1 -1
- data/vendor/depot_tools/yapf.bat +1 -1
- metadata +92 -77
- data/vendor/depot_tools/git-crsync +0 -3
- data/vendor/depot_tools/infra/config/cq.cfg +0 -32
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/apply_gerrit_ref.json +0 -29
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/apply_gerrit_ref_custom.json +0 -29
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/buildbot.json +0 -105
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/shallow.json +0 -195
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle_deprecated.json +0 -248
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8.json +0 -248
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_manifest_name_no_patch.json +0 -105
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/apply_gerrit.py +0 -33
- data/vendor/depot_tools/third_party/logilab/astroid/brain/py2pytest.py +0 -31
- data/vendor/depot_tools/third_party/logilab/astroid/brain/py2qt4.py +0 -22
- data/vendor/depot_tools/third_party/logilab/astroid/brain/py2stdlib.py +0 -334
- data/vendor/depot_tools/third_party/logilab/astroid/inspector.py +0 -273
- data/vendor/depot_tools/third_party/logilab/astroid/utils.py +0 -239
- data/vendor/depot_tools/third_party/logilab/common/LICENSE.txt +0 -339
- data/vendor/depot_tools/third_party/logilab/common/README.chromium +0 -11
- data/vendor/depot_tools/third_party/logilab/common/__init__.py +0 -175
- data/vendor/depot_tools/third_party/logilab/common/__pkginfo__.py +0 -57
- data/vendor/depot_tools/third_party/logilab/common/cache.py +0 -114
- data/vendor/depot_tools/third_party/logilab/common/changelog.py +0 -238
- data/vendor/depot_tools/third_party/logilab/common/clcommands.py +0 -334
- data/vendor/depot_tools/third_party/logilab/common/cli.py +0 -211
- data/vendor/depot_tools/third_party/logilab/common/compat.py +0 -78
- data/vendor/depot_tools/third_party/logilab/common/configuration.py +0 -1105
- data/vendor/depot_tools/third_party/logilab/common/contexts.py +0 -5
- data/vendor/depot_tools/third_party/logilab/common/corbautils.py +0 -117
- data/vendor/depot_tools/third_party/logilab/common/daemon.py +0 -101
- data/vendor/depot_tools/third_party/logilab/common/date.py +0 -335
- data/vendor/depot_tools/third_party/logilab/common/dbf.py +0 -231
- data/vendor/depot_tools/third_party/logilab/common/debugger.py +0 -214
- data/vendor/depot_tools/third_party/logilab/common/decorators.py +0 -281
- data/vendor/depot_tools/third_party/logilab/common/deprecation.py +0 -189
- data/vendor/depot_tools/third_party/logilab/common/fileutils.py +0 -404
- data/vendor/depot_tools/third_party/logilab/common/interface.py +0 -71
- data/vendor/depot_tools/third_party/logilab/common/logging_ext.py +0 -195
- data/vendor/depot_tools/third_party/logilab/common/modutils.py +0 -702
- data/vendor/depot_tools/third_party/logilab/common/optik_ext.py +0 -392
- data/vendor/depot_tools/third_party/logilab/common/optparser.py +0 -92
- data/vendor/depot_tools/third_party/logilab/common/proc.py +0 -277
- data/vendor/depot_tools/third_party/logilab/common/pyro_ext.py +0 -180
- data/vendor/depot_tools/third_party/logilab/common/pytest.py +0 -1199
- data/vendor/depot_tools/third_party/logilab/common/registry.py +0 -1119
- data/vendor/depot_tools/third_party/logilab/common/shellutils.py +0 -462
- data/vendor/depot_tools/third_party/logilab/common/sphinx_ext.py +0 -87
- data/vendor/depot_tools/third_party/logilab/common/sphinxutils.py +0 -122
- data/vendor/depot_tools/third_party/logilab/common/table.py +0 -929
- data/vendor/depot_tools/third_party/logilab/common/tasksqueue.py +0 -101
- data/vendor/depot_tools/third_party/logilab/common/testlib.py +0 -1392
- data/vendor/depot_tools/third_party/logilab/common/textutils.py +0 -537
- data/vendor/depot_tools/third_party/logilab/common/tree.py +0 -369
- data/vendor/depot_tools/third_party/logilab/common/umessage.py +0 -194
- data/vendor/depot_tools/third_party/logilab/common/ureports/__init__.py +0 -172
- data/vendor/depot_tools/third_party/logilab/common/ureports/docbook_writer.py +0 -140
- data/vendor/depot_tools/third_party/logilab/common/urllib2ext.py +0 -89
- data/vendor/depot_tools/third_party/logilab/common/visitor.py +0 -109
- data/vendor/depot_tools/third_party/logilab/common/xmlrpcutils.py +0 -131
- data/vendor/depot_tools/third_party/logilab/common/xmlutils.py +0 -61
@@ -1,1119 +0,0 @@
|
|
1
|
-
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
2
|
-
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
3
|
-
#
|
4
|
-
# This file is part of Logilab-common.
|
5
|
-
#
|
6
|
-
# Logilab-common is free software: you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as published by the
|
8
|
-
# Free Software Foundation, either version 2.1 of the License, or (at your
|
9
|
-
# option) any later version.
|
10
|
-
#
|
11
|
-
# Logilab-common is distributed in the hope that it will be useful, but WITHOUT
|
12
|
-
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
13
|
-
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
14
|
-
# details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public License along
|
17
|
-
# with Logilab-common. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
"""This module provides bases for predicates dispatching (the pattern in use
|
19
|
-
here is similar to what's refered as multi-dispatch or predicate-dispatch in the
|
20
|
-
literature, though a bit different since the idea is to select across different
|
21
|
-
implementation 'e.g. classes), not to dispatch a message to a function or
|
22
|
-
method. It contains the following classes:
|
23
|
-
|
24
|
-
* :class:`RegistryStore`, the top level object which loads implementation
|
25
|
-
objects and stores them into registries. You'll usually use it to access
|
26
|
-
registries and their contained objects;
|
27
|
-
|
28
|
-
* :class:`Registry`, the base class which contains objects semantically grouped
|
29
|
-
(for instance, sharing a same API, hence the 'implementation' name). You'll
|
30
|
-
use it to select the proper implementation according to a context. Notice you
|
31
|
-
may use registries on their own without using the store.
|
32
|
-
|
33
|
-
.. Note::
|
34
|
-
|
35
|
-
implementation objects are usually designed to be accessed through the
|
36
|
-
registry and not by direct instantiation, besides to use it as base classe.
|
37
|
-
|
38
|
-
The selection procedure is delegated to a selector, which is responsible for
|
39
|
-
scoring the object according to some context. At the end of the selection, if an
|
40
|
-
implementation has been found, an instance of this class is returned. A selector
|
41
|
-
is built from one or more predicates combined together using AND, OR, NOT
|
42
|
-
operators (actually `&`, `|` and `~`). You'll thus find some base classes to
|
43
|
-
build predicates:
|
44
|
-
|
45
|
-
* :class:`Predicate`, the abstract base predicate class
|
46
|
-
|
47
|
-
* :class:`AndPredicate`, :class:`OrPredicate`, :class:`NotPredicate`, which you
|
48
|
-
shouldn't have to use directly. You'll use `&`, `|` and '~' operators between
|
49
|
-
predicates directly
|
50
|
-
|
51
|
-
* :func:`objectify_predicate`
|
52
|
-
|
53
|
-
You'll eventually find one concrete predicate: :class:`yes`
|
54
|
-
|
55
|
-
.. autoclass:: RegistryStore
|
56
|
-
.. autoclass:: Registry
|
57
|
-
|
58
|
-
Predicates
|
59
|
-
----------
|
60
|
-
.. autoclass:: Predicate
|
61
|
-
.. autofunc:: objectify_predicate
|
62
|
-
.. autoclass:: yes
|
63
|
-
|
64
|
-
Debugging
|
65
|
-
---------
|
66
|
-
.. autoclass:: traced_selection
|
67
|
-
|
68
|
-
Exceptions
|
69
|
-
----------
|
70
|
-
.. autoclass:: RegistryException
|
71
|
-
.. autoclass:: RegistryNotFound
|
72
|
-
.. autoclass:: ObjectNotFound
|
73
|
-
.. autoclass:: NoSelectableObject
|
74
|
-
"""
|
75
|
-
|
76
|
-
from __future__ import print_function
|
77
|
-
|
78
|
-
__docformat__ = "restructuredtext en"
|
79
|
-
|
80
|
-
import sys
|
81
|
-
import types
|
82
|
-
import weakref
|
83
|
-
import traceback as tb
|
84
|
-
from os import listdir, stat
|
85
|
-
from os.path import join, isdir, exists
|
86
|
-
from logging import getLogger
|
87
|
-
from warnings import warn
|
88
|
-
|
89
|
-
from six import string_types, add_metaclass
|
90
|
-
|
91
|
-
from logilab.common.modutils import modpath_from_file
|
92
|
-
from logilab.common.logging_ext import set_log_methods
|
93
|
-
from logilab.common.decorators import classproperty
|
94
|
-
|
95
|
-
|
96
|
-
class RegistryException(Exception):
|
97
|
-
"""Base class for registry exception."""
|
98
|
-
|
99
|
-
class RegistryNotFound(RegistryException):
|
100
|
-
"""Raised when an unknown registry is requested.
|
101
|
-
|
102
|
-
This is usually a programming/typo error.
|
103
|
-
"""
|
104
|
-
|
105
|
-
class ObjectNotFound(RegistryException):
|
106
|
-
"""Raised when an unregistered object is requested.
|
107
|
-
|
108
|
-
This may be a programming/typo or a misconfiguration error.
|
109
|
-
"""
|
110
|
-
|
111
|
-
class NoSelectableObject(RegistryException):
|
112
|
-
"""Raised when no object is selectable for a given context."""
|
113
|
-
def __init__(self, args, kwargs, objects):
|
114
|
-
self.args = args
|
115
|
-
self.kwargs = kwargs
|
116
|
-
self.objects = objects
|
117
|
-
|
118
|
-
def __str__(self):
|
119
|
-
return ('args: %s, kwargs: %s\ncandidates: %s'
|
120
|
-
% (self.args, self.kwargs.keys(), self.objects))
|
121
|
-
|
122
|
-
|
123
|
-
def _modname_from_path(path, extrapath=None):
|
124
|
-
modpath = modpath_from_file(path, extrapath)
|
125
|
-
# omit '__init__' from package's name to avoid loading that module
|
126
|
-
# once for each name when it is imported by some other object
|
127
|
-
# module. This supposes import in modules are done as::
|
128
|
-
#
|
129
|
-
# from package import something
|
130
|
-
#
|
131
|
-
# not::
|
132
|
-
#
|
133
|
-
# from package.__init__ import something
|
134
|
-
#
|
135
|
-
# which seems quite correct.
|
136
|
-
if modpath[-1] == '__init__':
|
137
|
-
modpath.pop()
|
138
|
-
return '.'.join(modpath)
|
139
|
-
|
140
|
-
|
141
|
-
def _toload_info(path, extrapath, _toload=None):
|
142
|
-
"""Return a dictionary of <modname>: <modpath> and an ordered list of
|
143
|
-
(file, module name) to load
|
144
|
-
"""
|
145
|
-
if _toload is None:
|
146
|
-
assert isinstance(path, list)
|
147
|
-
_toload = {}, []
|
148
|
-
for fileordir in path:
|
149
|
-
if isdir(fileordir) and exists(join(fileordir, '__init__.py')):
|
150
|
-
subfiles = [join(fileordir, fname) for fname in listdir(fileordir)]
|
151
|
-
_toload_info(subfiles, extrapath, _toload)
|
152
|
-
elif fileordir[-3:] == '.py':
|
153
|
-
modname = _modname_from_path(fileordir, extrapath)
|
154
|
-
_toload[0][modname] = fileordir
|
155
|
-
_toload[1].append((fileordir, modname))
|
156
|
-
return _toload
|
157
|
-
|
158
|
-
|
159
|
-
class RegistrableObject(object):
|
160
|
-
"""This is the base class for registrable objects which are selected
|
161
|
-
according to a context.
|
162
|
-
|
163
|
-
:attr:`__registry__`
|
164
|
-
name of the registry for this object (string like 'views',
|
165
|
-
'templates'...). You may want to define `__registries__` directly if your
|
166
|
-
object should be registered in several registries.
|
167
|
-
|
168
|
-
:attr:`__regid__`
|
169
|
-
object's identifier in the registry (string like 'main',
|
170
|
-
'primary', 'folder_box')
|
171
|
-
|
172
|
-
:attr:`__select__`
|
173
|
-
class'selector
|
174
|
-
|
175
|
-
Moreover, the `__abstract__` attribute may be set to True to indicate that a
|
176
|
-
class is abstract and should not be registered.
|
177
|
-
|
178
|
-
You don't have to inherit from this class to put it in a registry (having
|
179
|
-
`__regid__` and `__select__` is enough), though this is needed for classes
|
180
|
-
that should be automatically registered.
|
181
|
-
"""
|
182
|
-
|
183
|
-
__registry__ = None
|
184
|
-
__regid__ = None
|
185
|
-
__select__ = None
|
186
|
-
__abstract__ = True # see doc snipppets below (in Registry class)
|
187
|
-
|
188
|
-
@classproperty
|
189
|
-
def __registries__(cls):
|
190
|
-
if cls.__registry__ is None:
|
191
|
-
return ()
|
192
|
-
return (cls.__registry__,)
|
193
|
-
|
194
|
-
|
195
|
-
class RegistrableInstance(RegistrableObject):
|
196
|
-
"""Inherit this class if you want instances of the classes to be
|
197
|
-
automatically registered.
|
198
|
-
"""
|
199
|
-
|
200
|
-
def __new__(cls, *args, **kwargs):
|
201
|
-
"""Add a __module__ attribute telling the module where the instance was
|
202
|
-
created, for automatic registration.
|
203
|
-
"""
|
204
|
-
obj = super(RegistrableInstance, cls).__new__(cls)
|
205
|
-
# XXX subclass must no override __new__
|
206
|
-
filepath = tb.extract_stack(limit=2)[0][0]
|
207
|
-
obj.__module__ = _modname_from_path(filepath)
|
208
|
-
return obj
|
209
|
-
|
210
|
-
|
211
|
-
class Registry(dict):
|
212
|
-
"""The registry store a set of implementations associated to identifier:
|
213
|
-
|
214
|
-
* to each identifier are associated a list of implementations
|
215
|
-
|
216
|
-
* to select an implementation of a given identifier, you should use one of the
|
217
|
-
:meth:`select` or :meth:`select_or_none` method
|
218
|
-
|
219
|
-
* to select a list of implementations for a context, you should use the
|
220
|
-
:meth:`possible_objects` method
|
221
|
-
|
222
|
-
* dictionary like access to an identifier will return the bare list of
|
223
|
-
implementations for this identifier.
|
224
|
-
|
225
|
-
To be usable in a registry, the only requirement is to have a `__select__`
|
226
|
-
attribute.
|
227
|
-
|
228
|
-
At the end of the registration process, the :meth:`__registered__`
|
229
|
-
method is called on each registered object which have them, given the
|
230
|
-
registry in which it's registered as argument.
|
231
|
-
|
232
|
-
Registration methods:
|
233
|
-
|
234
|
-
.. automethod: register
|
235
|
-
.. automethod: unregister
|
236
|
-
|
237
|
-
Selection methods:
|
238
|
-
|
239
|
-
.. automethod: select
|
240
|
-
.. automethod: select_or_none
|
241
|
-
.. automethod: possible_objects
|
242
|
-
.. automethod: object_by_id
|
243
|
-
"""
|
244
|
-
def __init__(self, debugmode):
|
245
|
-
super(Registry, self).__init__()
|
246
|
-
self.debugmode = debugmode
|
247
|
-
|
248
|
-
def __getitem__(self, name):
|
249
|
-
"""return the registry (list of implementation objects) associated to
|
250
|
-
this name
|
251
|
-
"""
|
252
|
-
try:
|
253
|
-
return super(Registry, self).__getitem__(name)
|
254
|
-
except KeyError:
|
255
|
-
exc = ObjectNotFound(name)
|
256
|
-
exc.__traceback__ = sys.exc_info()[-1]
|
257
|
-
raise exc
|
258
|
-
|
259
|
-
@classmethod
|
260
|
-
def objid(cls, obj):
|
261
|
-
"""returns a unique identifier for an object stored in the registry"""
|
262
|
-
return '%s.%s' % (obj.__module__, cls.objname(obj))
|
263
|
-
|
264
|
-
@classmethod
|
265
|
-
def objname(cls, obj):
|
266
|
-
"""returns a readable name for an object stored in the registry"""
|
267
|
-
return getattr(obj, '__name__', id(obj))
|
268
|
-
|
269
|
-
def initialization_completed(self):
|
270
|
-
"""call method __registered__() on registered objects when the callback
|
271
|
-
is defined"""
|
272
|
-
for objects in self.values():
|
273
|
-
for objectcls in objects:
|
274
|
-
registered = getattr(objectcls, '__registered__', None)
|
275
|
-
if registered:
|
276
|
-
registered(self)
|
277
|
-
if self.debugmode:
|
278
|
-
wrap_predicates(_lltrace)
|
279
|
-
|
280
|
-
def register(self, obj, oid=None, clear=False):
|
281
|
-
"""base method to add an object in the registry"""
|
282
|
-
assert not '__abstract__' in obj.__dict__, obj
|
283
|
-
assert obj.__select__, obj
|
284
|
-
oid = oid or obj.__regid__
|
285
|
-
assert oid, ('no explicit name supplied to register object %s, '
|
286
|
-
'which has no __regid__ set' % obj)
|
287
|
-
if clear:
|
288
|
-
objects = self[oid] = []
|
289
|
-
else:
|
290
|
-
objects = self.setdefault(oid, [])
|
291
|
-
assert not obj in objects, 'object %s is already registered' % obj
|
292
|
-
objects.append(obj)
|
293
|
-
|
294
|
-
def register_and_replace(self, obj, replaced):
|
295
|
-
"""remove <replaced> and register <obj>"""
|
296
|
-
# XXXFIXME this is a duplication of unregister()
|
297
|
-
# remove register_and_replace in favor of unregister + register
|
298
|
-
# or simplify by calling unregister then register here
|
299
|
-
if not isinstance(replaced, string_types):
|
300
|
-
replaced = self.objid(replaced)
|
301
|
-
# prevent from misspelling
|
302
|
-
assert obj is not replaced, 'replacing an object by itself: %s' % obj
|
303
|
-
registered_objs = self.get(obj.__regid__, ())
|
304
|
-
for index, registered in enumerate(registered_objs):
|
305
|
-
if self.objid(registered) == replaced:
|
306
|
-
del registered_objs[index]
|
307
|
-
break
|
308
|
-
else:
|
309
|
-
self.warning('trying to replace %s that is not registered with %s',
|
310
|
-
replaced, obj)
|
311
|
-
self.register(obj)
|
312
|
-
|
313
|
-
def unregister(self, obj):
|
314
|
-
"""remove object <obj> from this registry"""
|
315
|
-
objid = self.objid(obj)
|
316
|
-
oid = obj.__regid__
|
317
|
-
for registered in self.get(oid, ()):
|
318
|
-
# use self.objid() to compare objects because vreg will probably
|
319
|
-
# have its own version of the object, loaded through execfile
|
320
|
-
if self.objid(registered) == objid:
|
321
|
-
self[oid].remove(registered)
|
322
|
-
break
|
323
|
-
else:
|
324
|
-
self.warning('can\'t remove %s, no id %s in the registry',
|
325
|
-
objid, oid)
|
326
|
-
|
327
|
-
def all_objects(self):
|
328
|
-
"""return a list containing all objects in this registry.
|
329
|
-
"""
|
330
|
-
result = []
|
331
|
-
for objs in self.values():
|
332
|
-
result += objs
|
333
|
-
return result
|
334
|
-
|
335
|
-
# dynamic selection methods ################################################
|
336
|
-
|
337
|
-
def object_by_id(self, oid, *args, **kwargs):
|
338
|
-
"""return object with the `oid` identifier. Only one object is expected
|
339
|
-
to be found.
|
340
|
-
|
341
|
-
raise :exc:`ObjectNotFound` if there are no object with id `oid` in this
|
342
|
-
registry
|
343
|
-
|
344
|
-
raise :exc:`AssertionError` if there is more than one object there
|
345
|
-
"""
|
346
|
-
objects = self[oid]
|
347
|
-
assert len(objects) == 1, objects
|
348
|
-
return objects[0](*args, **kwargs)
|
349
|
-
|
350
|
-
def select(self, __oid, *args, **kwargs):
|
351
|
-
"""return the most specific object among those with the given oid
|
352
|
-
according to the given context.
|
353
|
-
|
354
|
-
raise :exc:`ObjectNotFound` if there are no object with id `oid` in this
|
355
|
-
registry
|
356
|
-
|
357
|
-
raise :exc:`NoSelectableObject` if no object can be selected
|
358
|
-
"""
|
359
|
-
obj = self._select_best(self[__oid], *args, **kwargs)
|
360
|
-
if obj is None:
|
361
|
-
raise NoSelectableObject(args, kwargs, self[__oid] )
|
362
|
-
return obj
|
363
|
-
|
364
|
-
def select_or_none(self, __oid, *args, **kwargs):
|
365
|
-
"""return the most specific object among those with the given oid
|
366
|
-
according to the given context, or None if no object applies.
|
367
|
-
"""
|
368
|
-
try:
|
369
|
-
return self._select_best(self[__oid], *args, **kwargs)
|
370
|
-
except ObjectNotFound:
|
371
|
-
return None
|
372
|
-
|
373
|
-
def possible_objects(self, *args, **kwargs):
|
374
|
-
"""return an iterator on possible objects in this registry for the given
|
375
|
-
context
|
376
|
-
"""
|
377
|
-
for objects in self.values():
|
378
|
-
obj = self._select_best(objects, *args, **kwargs)
|
379
|
-
if obj is None:
|
380
|
-
continue
|
381
|
-
yield obj
|
382
|
-
|
383
|
-
def _select_best(self, objects, *args, **kwargs):
|
384
|
-
"""return an instance of the most specific object according
|
385
|
-
to parameters
|
386
|
-
|
387
|
-
return None if not object apply (don't raise `NoSelectableObject` since
|
388
|
-
it's costly when searching objects using `possible_objects`
|
389
|
-
(e.g. searching for hooks).
|
390
|
-
"""
|
391
|
-
score, winners = 0, None
|
392
|
-
for obj in objects:
|
393
|
-
objectscore = obj.__select__(obj, *args, **kwargs)
|
394
|
-
if objectscore > score:
|
395
|
-
score, winners = objectscore, [obj]
|
396
|
-
elif objectscore > 0 and objectscore == score:
|
397
|
-
winners.append(obj)
|
398
|
-
if winners is None:
|
399
|
-
return None
|
400
|
-
if len(winners) > 1:
|
401
|
-
# log in production environement / test, error while debugging
|
402
|
-
msg = 'select ambiguity: %s\n(args: %s, kwargs: %s)'
|
403
|
-
if self.debugmode:
|
404
|
-
# raise bare exception in debug mode
|
405
|
-
raise Exception(msg % (winners, args, kwargs.keys()))
|
406
|
-
self.error(msg, winners, args, kwargs.keys())
|
407
|
-
# return the result of calling the object
|
408
|
-
return self.selected(winners[0], args, kwargs)
|
409
|
-
|
410
|
-
def selected(self, winner, args, kwargs):
|
411
|
-
"""override here if for instance you don't want "instanciation"
|
412
|
-
"""
|
413
|
-
return winner(*args, **kwargs)
|
414
|
-
|
415
|
-
# these are overridden by set_log_methods below
|
416
|
-
# only defining here to prevent pylint from complaining
|
417
|
-
info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
|
418
|
-
|
419
|
-
|
420
|
-
def obj_registries(cls, registryname=None):
|
421
|
-
"""return a tuple of registry names (see __registries__)"""
|
422
|
-
if registryname:
|
423
|
-
return (registryname,)
|
424
|
-
return cls.__registries__
|
425
|
-
|
426
|
-
|
427
|
-
class RegistryStore(dict):
|
428
|
-
"""This class is responsible for loading objects and storing them
|
429
|
-
in their registry which is created on the fly as needed.
|
430
|
-
|
431
|
-
It handles dynamic registration of objects and provides a
|
432
|
-
convenient api to access them. To be recognized as an object that
|
433
|
-
should be stored into one of the store's registry
|
434
|
-
(:class:`Registry`), an object must provide the following
|
435
|
-
attributes, used control how they interact with the registry:
|
436
|
-
|
437
|
-
:attr:`__registries__`
|
438
|
-
list of registry names (string like 'views', 'templates'...) into which
|
439
|
-
the object should be registered
|
440
|
-
|
441
|
-
:attr:`__regid__`
|
442
|
-
object identifier in the registry (string like 'main',
|
443
|
-
'primary', 'folder_box')
|
444
|
-
|
445
|
-
:attr:`__select__`
|
446
|
-
the object predicate selectors
|
447
|
-
|
448
|
-
Moreover, the :attr:`__abstract__` attribute may be set to `True`
|
449
|
-
to indicate that an object is abstract and should not be registered
|
450
|
-
(such inherited attributes not considered).
|
451
|
-
|
452
|
-
.. Note::
|
453
|
-
|
454
|
-
When using the store to load objects dynamically, you *always* have
|
455
|
-
to use **super()** to get the methods and attributes of the
|
456
|
-
superclasses, and not use the class identifier. If not, you'll get into
|
457
|
-
trouble at reload time.
|
458
|
-
|
459
|
-
For example, instead of writing::
|
460
|
-
|
461
|
-
class Thing(Parent):
|
462
|
-
__regid__ = 'athing'
|
463
|
-
__select__ = yes()
|
464
|
-
|
465
|
-
def f(self, arg1):
|
466
|
-
Parent.f(self, arg1)
|
467
|
-
|
468
|
-
You must write::
|
469
|
-
|
470
|
-
class Thing(Parent):
|
471
|
-
__regid__ = 'athing'
|
472
|
-
__select__ = yes()
|
473
|
-
|
474
|
-
def f(self, arg1):
|
475
|
-
super(Thing, self).f(arg1)
|
476
|
-
|
477
|
-
Controlling object registration
|
478
|
-
-------------------------------
|
479
|
-
|
480
|
-
Dynamic loading is triggered by calling the
|
481
|
-
:meth:`register_objects` method, given a list of directories to
|
482
|
-
inspect for python modules.
|
483
|
-
|
484
|
-
.. automethod: register_objects
|
485
|
-
|
486
|
-
For each module, by default, all compatible objects are registered
|
487
|
-
automatically. However if some objects come as replacement of
|
488
|
-
other objects, or have to be included only if some condition is
|
489
|
-
met, you'll have to define a `registration_callback(vreg)`
|
490
|
-
function in the module and explicitly register **all objects** in
|
491
|
-
this module, using the api defined below.
|
492
|
-
|
493
|
-
|
494
|
-
.. automethod:: RegistryStore.register_all
|
495
|
-
.. automethod:: RegistryStore.register_and_replace
|
496
|
-
.. automethod:: RegistryStore.register
|
497
|
-
.. automethod:: RegistryStore.unregister
|
498
|
-
|
499
|
-
.. Note::
|
500
|
-
Once the function `registration_callback(vreg)` is implemented in a
|
501
|
-
module, all the objects from this module have to be explicitly
|
502
|
-
registered as it disables the automatic object registration.
|
503
|
-
|
504
|
-
|
505
|
-
Examples:
|
506
|
-
|
507
|
-
.. sourcecode:: python
|
508
|
-
|
509
|
-
def registration_callback(store):
|
510
|
-
# register everything in the module except BabarClass
|
511
|
-
store.register_all(globals().values(), __name__, (BabarClass,))
|
512
|
-
|
513
|
-
# conditionally register BabarClass
|
514
|
-
if 'babar_relation' in store.schema:
|
515
|
-
store.register(BabarClass)
|
516
|
-
|
517
|
-
In this example, we register all application object classes defined in the module
|
518
|
-
except `BabarClass`. This class is then registered only if the 'babar_relation'
|
519
|
-
relation type is defined in the instance schema.
|
520
|
-
|
521
|
-
.. sourcecode:: python
|
522
|
-
|
523
|
-
def registration_callback(store):
|
524
|
-
store.register(Elephant)
|
525
|
-
# replace Babar by Celeste
|
526
|
-
store.register_and_replace(Celeste, Babar)
|
527
|
-
|
528
|
-
In this example, we explicitly register classes one by one:
|
529
|
-
|
530
|
-
* the `Elephant` class
|
531
|
-
* the `Celeste` to replace `Babar`
|
532
|
-
|
533
|
-
If at some point we register a new appobject class in this module, it won't be
|
534
|
-
registered at all without modification to the `registration_callback`
|
535
|
-
implementation. The first example will register it though, thanks to the call
|
536
|
-
to the `register_all` method.
|
537
|
-
|
538
|
-
Controlling registry instantiation
|
539
|
-
----------------------------------
|
540
|
-
|
541
|
-
The `REGISTRY_FACTORY` class dictionary allows to specify which class should
|
542
|
-
be instantiated for a given registry name. The class associated to `None`
|
543
|
-
key will be the class used when there is no specific class for a name.
|
544
|
-
"""
|
545
|
-
|
546
|
-
def __init__(self, debugmode=False):
|
547
|
-
super(RegistryStore, self).__init__()
|
548
|
-
self.debugmode = debugmode
|
549
|
-
|
550
|
-
def reset(self):
|
551
|
-
"""clear all registries managed by this store"""
|
552
|
-
# don't use self.clear, we want to keep existing subdictionaries
|
553
|
-
for subdict in self.values():
|
554
|
-
subdict.clear()
|
555
|
-
self._lastmodifs = {}
|
556
|
-
|
557
|
-
def __getitem__(self, name):
|
558
|
-
"""return the registry (dictionary of class objects) associated to
|
559
|
-
this name
|
560
|
-
"""
|
561
|
-
try:
|
562
|
-
return super(RegistryStore, self).__getitem__(name)
|
563
|
-
except KeyError:
|
564
|
-
exc = RegistryNotFound(name)
|
565
|
-
exc.__traceback__ = sys.exc_info()[-1]
|
566
|
-
raise exc
|
567
|
-
|
568
|
-
# methods for explicit (un)registration ###################################
|
569
|
-
|
570
|
-
# default class, when no specific class set
|
571
|
-
REGISTRY_FACTORY = {None: Registry}
|
572
|
-
|
573
|
-
def registry_class(self, regid):
|
574
|
-
"""return existing registry named regid or use factory to create one and
|
575
|
-
return it"""
|
576
|
-
try:
|
577
|
-
return self.REGISTRY_FACTORY[regid]
|
578
|
-
except KeyError:
|
579
|
-
return self.REGISTRY_FACTORY[None]
|
580
|
-
|
581
|
-
def setdefault(self, regid):
|
582
|
-
try:
|
583
|
-
return self[regid]
|
584
|
-
except RegistryNotFound:
|
585
|
-
self[regid] = self.registry_class(regid)(self.debugmode)
|
586
|
-
return self[regid]
|
587
|
-
|
588
|
-
def register_all(self, objects, modname, butclasses=()):
|
589
|
-
"""register registrable objects into `objects`.
|
590
|
-
|
591
|
-
Registrable objects are properly configured subclasses of
|
592
|
-
:class:`RegistrableObject`. Objects which are not defined in the module
|
593
|
-
`modname` or which are in `butclasses` won't be registered.
|
594
|
-
|
595
|
-
Typical usage is:
|
596
|
-
|
597
|
-
.. sourcecode:: python
|
598
|
-
|
599
|
-
store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))
|
600
|
-
|
601
|
-
So you get partially automatic registration, keeping manual registration
|
602
|
-
for some object (to use
|
603
|
-
:meth:`~logilab.common.registry.RegistryStore.register_and_replace` for
|
604
|
-
instance).
|
605
|
-
"""
|
606
|
-
assert isinstance(modname, string_types), \
|
607
|
-
'modname expected to be a module name (ie string), got %r' % modname
|
608
|
-
for obj in objects:
|
609
|
-
if self.is_registrable(obj) and obj.__module__ == modname and not obj in butclasses:
|
610
|
-
if isinstance(obj, type):
|
611
|
-
self._load_ancestors_then_object(modname, obj, butclasses)
|
612
|
-
else:
|
613
|
-
self.register(obj)
|
614
|
-
|
615
|
-
def register(self, obj, registryname=None, oid=None, clear=False):
|
616
|
-
"""register `obj` implementation into `registryname` or
|
617
|
-
`obj.__registries__` if not specified, with identifier `oid` or
|
618
|
-
`obj.__regid__` if not specified.
|
619
|
-
|
620
|
-
If `clear` is true, all objects with the same identifier will be
|
621
|
-
previously unregistered.
|
622
|
-
"""
|
623
|
-
assert not obj.__dict__.get('__abstract__'), obj
|
624
|
-
for registryname in obj_registries(obj, registryname):
|
625
|
-
registry = self.setdefault(registryname)
|
626
|
-
registry.register(obj, oid=oid, clear=clear)
|
627
|
-
self.debug("register %s in %s['%s']",
|
628
|
-
registry.objname(obj), registryname, oid or obj.__regid__)
|
629
|
-
self._loadedmods.setdefault(obj.__module__, {})[registry.objid(obj)] = obj
|
630
|
-
|
631
|
-
def unregister(self, obj, registryname=None):
|
632
|
-
"""unregister `obj` object from the registry `registryname` or
|
633
|
-
`obj.__registries__` if not specified.
|
634
|
-
"""
|
635
|
-
for registryname in obj_registries(obj, registryname):
|
636
|
-
registry = self[registryname]
|
637
|
-
registry.unregister(obj)
|
638
|
-
self.debug("unregister %s from %s['%s']",
|
639
|
-
registry.objname(obj), registryname, obj.__regid__)
|
640
|
-
|
641
|
-
def register_and_replace(self, obj, replaced, registryname=None):
|
642
|
-
"""register `obj` object into `registryname` or
|
643
|
-
`obj.__registries__` if not specified. If found, the `replaced` object
|
644
|
-
will be unregistered first (else a warning will be issued as it is
|
645
|
-
generally unexpected).
|
646
|
-
"""
|
647
|
-
for registryname in obj_registries(obj, registryname):
|
648
|
-
registry = self[registryname]
|
649
|
-
registry.register_and_replace(obj, replaced)
|
650
|
-
self.debug("register %s in %s['%s'] instead of %s",
|
651
|
-
registry.objname(obj), registryname, obj.__regid__,
|
652
|
-
registry.objname(replaced))
|
653
|
-
|
654
|
-
# initialization methods ###################################################
|
655
|
-
|
656
|
-
def init_registration(self, path, extrapath=None):
|
657
|
-
"""reset registry and walk down path to return list of (path, name)
|
658
|
-
file modules to be loaded"""
|
659
|
-
# XXX make this private by renaming it to _init_registration ?
|
660
|
-
self.reset()
|
661
|
-
# compute list of all modules that have to be loaded
|
662
|
-
self._toloadmods, filemods = _toload_info(path, extrapath)
|
663
|
-
# XXX is _loadedmods still necessary ? It seems like it's useful
|
664
|
-
# to avoid loading same module twice, especially with the
|
665
|
-
# _load_ancestors_then_object logic but this needs to be checked
|
666
|
-
self._loadedmods = {}
|
667
|
-
return filemods
|
668
|
-
|
669
|
-
def register_objects(self, path, extrapath=None):
|
670
|
-
"""register all objects found walking down <path>"""
|
671
|
-
# load views from each directory in the instance's path
|
672
|
-
# XXX inline init_registration ?
|
673
|
-
filemods = self.init_registration(path, extrapath)
|
674
|
-
for filepath, modname in filemods:
|
675
|
-
self.load_file(filepath, modname)
|
676
|
-
self.initialization_completed()
|
677
|
-
|
678
|
-
def initialization_completed(self):
|
679
|
-
"""call initialization_completed() on all known registries"""
|
680
|
-
for reg in self.values():
|
681
|
-
reg.initialization_completed()
|
682
|
-
|
683
|
-
def _mdate(self, filepath):
|
684
|
-
""" return the modification date of a file path """
|
685
|
-
try:
|
686
|
-
return stat(filepath)[-2]
|
687
|
-
except OSError:
|
688
|
-
# this typically happens on emacs backup files (.#foo.py)
|
689
|
-
self.warning('Unable to load %s. It is likely to be a backup file',
|
690
|
-
filepath)
|
691
|
-
return None
|
692
|
-
|
693
|
-
def is_reload_needed(self, path):
|
694
|
-
"""return True if something module changed and the registry should be
|
695
|
-
reloaded
|
696
|
-
"""
|
697
|
-
lastmodifs = self._lastmodifs
|
698
|
-
for fileordir in path:
|
699
|
-
if isdir(fileordir) and exists(join(fileordir, '__init__.py')):
|
700
|
-
if self.is_reload_needed([join(fileordir, fname)
|
701
|
-
for fname in listdir(fileordir)]):
|
702
|
-
return True
|
703
|
-
elif fileordir[-3:] == '.py':
|
704
|
-
mdate = self._mdate(fileordir)
|
705
|
-
if mdate is None:
|
706
|
-
continue # backup file, see _mdate implementation
|
707
|
-
elif "flymake" in fileordir:
|
708
|
-
# flymake + pylint in use, don't consider these they will corrupt the registry
|
709
|
-
continue
|
710
|
-
if fileordir not in lastmodifs or lastmodifs[fileordir] < mdate:
|
711
|
-
self.info('File %s changed since last visit', fileordir)
|
712
|
-
return True
|
713
|
-
return False
|
714
|
-
|
715
|
-
def load_file(self, filepath, modname):
|
716
|
-
""" load registrable objects (if any) from a python file """
|
717
|
-
from logilab.common.modutils import load_module_from_name
|
718
|
-
if modname in self._loadedmods:
|
719
|
-
return
|
720
|
-
self._loadedmods[modname] = {}
|
721
|
-
mdate = self._mdate(filepath)
|
722
|
-
if mdate is None:
|
723
|
-
return # backup file, see _mdate implementation
|
724
|
-
elif "flymake" in filepath:
|
725
|
-
# flymake + pylint in use, don't consider these they will corrupt the registry
|
726
|
-
return
|
727
|
-
# set update time before module loading, else we get some reloading
|
728
|
-
# weirdness in case of syntax error or other error while importing the
|
729
|
-
# module
|
730
|
-
self._lastmodifs[filepath] = mdate
|
731
|
-
# load the module
|
732
|
-
module = load_module_from_name(modname)
|
733
|
-
self.load_module(module)
|
734
|
-
|
735
|
-
def load_module(self, module):
|
736
|
-
"""Automatically handle module objects registration.
|
737
|
-
|
738
|
-
Instances are registered as soon as they are hashable and have the
|
739
|
-
following attributes:
|
740
|
-
|
741
|
-
* __regid__ (a string)
|
742
|
-
* __select__ (a callable)
|
743
|
-
* __registries__ (a tuple/list of string)
|
744
|
-
|
745
|
-
For classes this is a bit more complicated :
|
746
|
-
|
747
|
-
- first ensure parent classes are already registered
|
748
|
-
|
749
|
-
- class with __abstract__ == True in their local dictionary are skipped
|
750
|
-
|
751
|
-
- object class needs to have registries and identifier properly set to a
|
752
|
-
non empty string to be registered.
|
753
|
-
"""
|
754
|
-
self.info('loading %s from %s', module.__name__, module.__file__)
|
755
|
-
if hasattr(module, 'registration_callback'):
|
756
|
-
module.registration_callback(self)
|
757
|
-
else:
|
758
|
-
self.register_all(vars(module).values(), module.__name__)
|
759
|
-
|
760
|
-
def _load_ancestors_then_object(self, modname, objectcls, butclasses=()):
|
761
|
-
"""handle class registration according to rules defined in
|
762
|
-
:meth:`load_module`
|
763
|
-
"""
|
764
|
-
# backward compat, we used to allow whatever else than classes
|
765
|
-
if not isinstance(objectcls, type):
|
766
|
-
if self.is_registrable(objectcls) and objectcls.__module__ == modname:
|
767
|
-
self.register(objectcls)
|
768
|
-
return
|
769
|
-
# imported classes
|
770
|
-
objmodname = objectcls.__module__
|
771
|
-
if objmodname != modname:
|
772
|
-
# The module of the object is not the same as the currently
|
773
|
-
# worked on module, or this is actually an instance, which
|
774
|
-
# has no module at all
|
775
|
-
if objmodname in self._toloadmods:
|
776
|
-
# if this is still scheduled for loading, let's proceed immediately,
|
777
|
-
# but using the object module
|
778
|
-
self.load_file(self._toloadmods[objmodname], objmodname)
|
779
|
-
return
|
780
|
-
# ensure object hasn't been already processed
|
781
|
-
clsid = '%s.%s' % (modname, objectcls.__name__)
|
782
|
-
if clsid in self._loadedmods[modname]:
|
783
|
-
return
|
784
|
-
self._loadedmods[modname][clsid] = objectcls
|
785
|
-
# ensure ancestors are registered
|
786
|
-
for parent in objectcls.__bases__:
|
787
|
-
self._load_ancestors_then_object(modname, parent, butclasses)
|
788
|
-
# ensure object is registrable
|
789
|
-
if objectcls in butclasses or not self.is_registrable(objectcls):
|
790
|
-
return
|
791
|
-
# backward compat
|
792
|
-
reg = self.setdefault(obj_registries(objectcls)[0])
|
793
|
-
if reg.objname(objectcls)[0] == '_':
|
794
|
-
warn("[lgc 0.59] object whose name start with '_' won't be "
|
795
|
-
"skipped anymore at some point, use __abstract__ = True "
|
796
|
-
"instead (%s)" % objectcls, DeprecationWarning)
|
797
|
-
return
|
798
|
-
# register, finally
|
799
|
-
self.register(objectcls)
|
800
|
-
|
801
|
-
@classmethod
|
802
|
-
def is_registrable(cls, obj):
|
803
|
-
"""ensure `obj` should be registered
|
804
|
-
|
805
|
-
as arbitrary stuff may be registered, do a lot of check and warn about
|
806
|
-
weird cases (think to dumb proxy objects)
|
807
|
-
"""
|
808
|
-
if isinstance(obj, type):
|
809
|
-
if not issubclass(obj, RegistrableObject):
|
810
|
-
# ducktyping backward compat
|
811
|
-
if not (getattr(obj, '__registries__', None)
|
812
|
-
and getattr(obj, '__regid__', None)
|
813
|
-
and getattr(obj, '__select__', None)):
|
814
|
-
return False
|
815
|
-
elif issubclass(obj, RegistrableInstance):
|
816
|
-
return False
|
817
|
-
elif not isinstance(obj, RegistrableInstance):
|
818
|
-
return False
|
819
|
-
if not obj.__regid__:
|
820
|
-
return False # no regid
|
821
|
-
registries = obj.__registries__
|
822
|
-
if not registries:
|
823
|
-
return False # no registries
|
824
|
-
selector = obj.__select__
|
825
|
-
if not selector:
|
826
|
-
return False # no selector
|
827
|
-
if obj.__dict__.get('__abstract__', False):
|
828
|
-
return False
|
829
|
-
# then detect potential problems that should be warned
|
830
|
-
if not isinstance(registries, (tuple, list)):
|
831
|
-
cls.warning('%s has __registries__ which is not a list or tuple', obj)
|
832
|
-
return False
|
833
|
-
if not callable(selector):
|
834
|
-
cls.warning('%s has not callable __select__', obj)
|
835
|
-
return False
|
836
|
-
return True
|
837
|
-
|
838
|
-
# these are overridden by set_log_methods below
|
839
|
-
# only defining here to prevent pylint from complaining
|
840
|
-
info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
|
841
|
-
|
842
|
-
|
843
|
-
# init logging
|
844
|
-
set_log_methods(RegistryStore, getLogger('registry.store'))
|
845
|
-
set_log_methods(Registry, getLogger('registry'))
|
846
|
-
|
847
|
-
|
848
|
-
# helpers for debugging selectors
|
849
|
-
TRACED_OIDS = None
|
850
|
-
|
851
|
-
def _trace_selector(cls, selector, args, ret):
|
852
|
-
vobj = args[0]
|
853
|
-
if TRACED_OIDS == 'all' or vobj.__regid__ in TRACED_OIDS:
|
854
|
-
print('%s -> %s for %s(%s)' % (cls, ret, vobj, vobj.__regid__))
|
855
|
-
|
856
|
-
def _lltrace(selector):
|
857
|
-
"""use this decorator on your predicates so they become traceable with
|
858
|
-
:class:`traced_selection`
|
859
|
-
"""
|
860
|
-
def traced(cls, *args, **kwargs):
|
861
|
-
ret = selector(cls, *args, **kwargs)
|
862
|
-
if TRACED_OIDS is not None:
|
863
|
-
_trace_selector(cls, selector, args, ret)
|
864
|
-
return ret
|
865
|
-
traced.__name__ = selector.__name__
|
866
|
-
traced.__doc__ = selector.__doc__
|
867
|
-
return traced
|
868
|
-
|
869
|
-
class traced_selection(object): # pylint: disable=C0103
|
870
|
-
"""
|
871
|
-
Typical usage is :
|
872
|
-
|
873
|
-
.. sourcecode:: python
|
874
|
-
|
875
|
-
>>> from logilab.common.registry import traced_selection
|
876
|
-
>>> with traced_selection():
|
877
|
-
... # some code in which you want to debug selectors
|
878
|
-
... # for all objects
|
879
|
-
|
880
|
-
This will yield lines like this in the logs::
|
881
|
-
|
882
|
-
selector one_line_rset returned 0 for <class 'elephant.Babar'>
|
883
|
-
|
884
|
-
You can also give to :class:`traced_selection` the identifiers of objects on
|
885
|
-
which you want to debug selection ('oid1' and 'oid2' in the example above).
|
886
|
-
|
887
|
-
.. sourcecode:: python
|
888
|
-
|
889
|
-
>>> with traced_selection( ('regid1', 'regid2') ):
|
890
|
-
... # some code in which you want to debug selectors
|
891
|
-
... # for objects with __regid__ 'regid1' and 'regid2'
|
892
|
-
|
893
|
-
A potentially useful point to set up such a tracing function is
|
894
|
-
the `logilab.common.registry.Registry.select` method body.
|
895
|
-
"""
|
896
|
-
|
897
|
-
def __init__(self, traced='all'):
|
898
|
-
self.traced = traced
|
899
|
-
|
900
|
-
def __enter__(self):
|
901
|
-
global TRACED_OIDS
|
902
|
-
TRACED_OIDS = self.traced
|
903
|
-
|
904
|
-
def __exit__(self, exctype, exc, traceback):
|
905
|
-
global TRACED_OIDS
|
906
|
-
TRACED_OIDS = None
|
907
|
-
return traceback is None
|
908
|
-
|
909
|
-
# selector base classes and operations ########################################
|
910
|
-
|
911
|
-
def objectify_predicate(selector_func):
|
912
|
-
"""Most of the time, a simple score function is enough to build a selector.
|
913
|
-
The :func:`objectify_predicate` decorator turn it into a proper selector
|
914
|
-
class::
|
915
|
-
|
916
|
-
@objectify_predicate
|
917
|
-
def one(cls, req, rset=None, **kwargs):
|
918
|
-
return 1
|
919
|
-
|
920
|
-
class MyView(View):
|
921
|
-
__select__ = View.__select__ & one()
|
922
|
-
|
923
|
-
"""
|
924
|
-
return type(selector_func.__name__, (Predicate,),
|
925
|
-
{'__doc__': selector_func.__doc__,
|
926
|
-
'__call__': lambda self, *a, **kw: selector_func(*a, **kw)})
|
927
|
-
|
928
|
-
|
929
|
-
_PREDICATES = {}
|
930
|
-
|
931
|
-
def wrap_predicates(decorator):
|
932
|
-
for predicate in _PREDICATES.values():
|
933
|
-
if not '_decorators' in predicate.__dict__:
|
934
|
-
predicate._decorators = set()
|
935
|
-
if decorator in predicate._decorators:
|
936
|
-
continue
|
937
|
-
predicate._decorators.add(decorator)
|
938
|
-
predicate.__call__ = decorator(predicate.__call__)
|
939
|
-
|
940
|
-
class PredicateMetaClass(type):
|
941
|
-
def __new__(mcs, *args, **kwargs):
|
942
|
-
# use __new__ so subclasses doesn't have to call Predicate.__init__
|
943
|
-
inst = type.__new__(mcs, *args, **kwargs)
|
944
|
-
proxy = weakref.proxy(inst, lambda p: _PREDICATES.pop(id(p)))
|
945
|
-
_PREDICATES[id(proxy)] = proxy
|
946
|
-
return inst
|
947
|
-
|
948
|
-
|
949
|
-
@add_metaclass(PredicateMetaClass)
|
950
|
-
class Predicate(object):
|
951
|
-
"""base class for selector classes providing implementation
|
952
|
-
for operators ``&``, ``|`` and ``~``
|
953
|
-
|
954
|
-
This class is only here to give access to binary operators, the selector
|
955
|
-
logic itself should be implemented in the :meth:`__call__` method. Notice it
|
956
|
-
should usually accept any arbitrary arguments (the context), though that may
|
957
|
-
vary depending on your usage of the registry.
|
958
|
-
|
959
|
-
a selector is called to help choosing the correct object for a
|
960
|
-
particular context by returning a score (`int`) telling how well
|
961
|
-
the implementation given as first argument fit to the given context.
|
962
|
-
|
963
|
-
0 score means that the class doesn't apply.
|
964
|
-
"""
|
965
|
-
|
966
|
-
@property
|
967
|
-
def func_name(self):
|
968
|
-
# backward compatibility
|
969
|
-
return self.__class__.__name__
|
970
|
-
|
971
|
-
def search_selector(self, selector):
|
972
|
-
"""search for the given selector, selector instance or tuple of
|
973
|
-
selectors in the selectors tree. Return None if not found.
|
974
|
-
"""
|
975
|
-
if self is selector:
|
976
|
-
return self
|
977
|
-
if (isinstance(selector, type) or isinstance(selector, tuple)) and \
|
978
|
-
isinstance(self, selector):
|
979
|
-
return self
|
980
|
-
return None
|
981
|
-
|
982
|
-
def __str__(self):
|
983
|
-
return self.__class__.__name__
|
984
|
-
|
985
|
-
def __and__(self, other):
|
986
|
-
return AndPredicate(self, other)
|
987
|
-
def __rand__(self, other):
|
988
|
-
return AndPredicate(other, self)
|
989
|
-
def __iand__(self, other):
|
990
|
-
return AndPredicate(self, other)
|
991
|
-
def __or__(self, other):
|
992
|
-
return OrPredicate(self, other)
|
993
|
-
def __ror__(self, other):
|
994
|
-
return OrPredicate(other, self)
|
995
|
-
def __ior__(self, other):
|
996
|
-
return OrPredicate(self, other)
|
997
|
-
|
998
|
-
def __invert__(self):
|
999
|
-
return NotPredicate(self)
|
1000
|
-
|
1001
|
-
# XXX (function | function) or (function & function) not managed yet
|
1002
|
-
|
1003
|
-
def __call__(self, cls, *args, **kwargs):
|
1004
|
-
return NotImplementedError("selector %s must implement its logic "
|
1005
|
-
"in its __call__ method" % self.__class__)
|
1006
|
-
|
1007
|
-
def __repr__(self):
|
1008
|
-
return u'<Predicate %s at %x>' % (self.__class__.__name__, id(self))
|
1009
|
-
|
1010
|
-
|
1011
|
-
class MultiPredicate(Predicate):
|
1012
|
-
"""base class for compound selector classes"""
|
1013
|
-
|
1014
|
-
def __init__(self, *selectors):
|
1015
|
-
self.selectors = self.merge_selectors(selectors)
|
1016
|
-
|
1017
|
-
def __str__(self):
|
1018
|
-
return '%s(%s)' % (self.__class__.__name__,
|
1019
|
-
','.join(str(s) for s in self.selectors))
|
1020
|
-
|
1021
|
-
@classmethod
|
1022
|
-
def merge_selectors(cls, selectors):
|
1023
|
-
"""deal with selector instanciation when necessary and merge
|
1024
|
-
multi-selectors if possible:
|
1025
|
-
|
1026
|
-
AndPredicate(AndPredicate(sel1, sel2), AndPredicate(sel3, sel4))
|
1027
|
-
==> AndPredicate(sel1, sel2, sel3, sel4)
|
1028
|
-
"""
|
1029
|
-
merged_selectors = []
|
1030
|
-
for selector in selectors:
|
1031
|
-
# XXX do we really want magic-transformations below?
|
1032
|
-
# if so, wanna warn about them?
|
1033
|
-
if isinstance(selector, types.FunctionType):
|
1034
|
-
selector = objectify_predicate(selector)()
|
1035
|
-
if isinstance(selector, type) and issubclass(selector, Predicate):
|
1036
|
-
selector = selector()
|
1037
|
-
assert isinstance(selector, Predicate), selector
|
1038
|
-
if isinstance(selector, cls):
|
1039
|
-
merged_selectors += selector.selectors
|
1040
|
-
else:
|
1041
|
-
merged_selectors.append(selector)
|
1042
|
-
return merged_selectors
|
1043
|
-
|
1044
|
-
def search_selector(self, selector):
|
1045
|
-
"""search for the given selector or selector instance (or tuple of
|
1046
|
-
selectors) in the selectors tree. Return None if not found
|
1047
|
-
"""
|
1048
|
-
for childselector in self.selectors:
|
1049
|
-
if childselector is selector:
|
1050
|
-
return childselector
|
1051
|
-
found = childselector.search_selector(selector)
|
1052
|
-
if found is not None:
|
1053
|
-
return found
|
1054
|
-
# if not found in children, maybe we are looking for self?
|
1055
|
-
return super(MultiPredicate, self).search_selector(selector)
|
1056
|
-
|
1057
|
-
|
1058
|
-
class AndPredicate(MultiPredicate):
|
1059
|
-
"""and-chained selectors"""
|
1060
|
-
def __call__(self, cls, *args, **kwargs):
|
1061
|
-
score = 0
|
1062
|
-
for selector in self.selectors:
|
1063
|
-
partscore = selector(cls, *args, **kwargs)
|
1064
|
-
if not partscore:
|
1065
|
-
return 0
|
1066
|
-
score += partscore
|
1067
|
-
return score
|
1068
|
-
|
1069
|
-
|
1070
|
-
class OrPredicate(MultiPredicate):
|
1071
|
-
"""or-chained selectors"""
|
1072
|
-
def __call__(self, cls, *args, **kwargs):
|
1073
|
-
for selector in self.selectors:
|
1074
|
-
partscore = selector(cls, *args, **kwargs)
|
1075
|
-
if partscore:
|
1076
|
-
return partscore
|
1077
|
-
return 0
|
1078
|
-
|
1079
|
-
class NotPredicate(Predicate):
|
1080
|
-
"""negation selector"""
|
1081
|
-
def __init__(self, selector):
|
1082
|
-
self.selector = selector
|
1083
|
-
|
1084
|
-
def __call__(self, cls, *args, **kwargs):
|
1085
|
-
score = self.selector(cls, *args, **kwargs)
|
1086
|
-
return int(not score)
|
1087
|
-
|
1088
|
-
def __str__(self):
|
1089
|
-
return 'NOT(%s)' % self.selector
|
1090
|
-
|
1091
|
-
|
1092
|
-
class yes(Predicate): # pylint: disable=C0103
|
1093
|
-
"""Return the score given as parameter, with a default score of 0.5 so any
|
1094
|
-
other selector take precedence.
|
1095
|
-
|
1096
|
-
Usually used for objects which can be selected whatever the context, or
|
1097
|
-
also sometimes to add arbitrary points to a score.
|
1098
|
-
|
1099
|
-
Take care, `yes(0)` could be named 'no'...
|
1100
|
-
"""
|
1101
|
-
def __init__(self, score=0.5):
|
1102
|
-
self.score = score
|
1103
|
-
|
1104
|
-
def __call__(self, *args, **kwargs):
|
1105
|
-
return self.score
|
1106
|
-
|
1107
|
-
|
1108
|
-
# deprecated stuff #############################################################
|
1109
|
-
|
1110
|
-
from logilab.common.deprecation import deprecated
|
1111
|
-
|
1112
|
-
@deprecated('[lgc 0.59] use Registry.objid class method instead')
|
1113
|
-
def classid(cls):
|
1114
|
-
return '%s.%s' % (cls.__module__, cls.__name__)
|
1115
|
-
|
1116
|
-
@deprecated('[lgc 0.59] use obj_registries function instead')
|
1117
|
-
def class_registries(cls, registryname):
|
1118
|
-
return obj_registries(cls, registryname)
|
1119
|
-
|