From 337abb26c996eb3a21d7e1ef4c866ed11f9d9149 Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Mon, 18 Nov 2019 16:30:43 -0800 Subject: [PATCH] [metadata] consolidate MetadataWrapper methods to the same file --- libcst/metadata/_resolver.py | 63 ------------------- libcst/metadata/base_provider.py | 27 +------- libcst/metadata/tests/test_base_provider.py | 2 +- libcst/metadata/wrapper.py | 68 ++++++++++++++++++++- 4 files changed, 69 insertions(+), 91 deletions(-) delete mode 100644 libcst/metadata/_resolver.py diff --git a/libcst/metadata/_resolver.py b/libcst/metadata/_resolver.py deleted file mode 100644 index ac49db87..00000000 --- a/libcst/metadata/_resolver.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -# pyre-strict -from typing import TYPE_CHECKING, Collection, MutableSet - -from libcst._exceptions import MetadataException -from libcst.metadata.base_provider import ( - BatchableMetadataProvider, - ProviderT, - _gen_batchable, -) - - -if TYPE_CHECKING: - from libcst.metadata.wrapper import MetadataWrapper # noqa: F401 - - -def _gather_providers( - providers: Collection[ProviderT], gathered: MutableSet[ProviderT] -) -> MutableSet[ProviderT]: - """ - Recursively gathers all the given providers and their dependencies. - """ - for P in providers: - if P not in gathered: - gathered.add(P) - _gather_providers(P.METADATA_DEPENDENCIES, gathered) - return gathered - - -def _resolve_impl(wrapper: "MetadataWrapper", providers: Collection[ProviderT]) -> None: - """ - Updates the _metadata map on wrapper with metadata from the given providers - as well as their dependencies. - """ - providers = set(providers) - set(wrapper._metadata.keys()) - remaining = _gather_providers(providers, set()) - - completed = set() - while len(remaining) > 0: - batchable = set() - - for P in remaining: - if set(P.METADATA_DEPENDENCIES).issubset(completed): - if issubclass(P, BatchableMetadataProvider): - batchable.add(P) - else: - wrapper._metadata[P] = P()._gen(wrapper) - completed.add(P) - - metadata_batch = _gen_batchable(wrapper, [p() for p in batchable]) - wrapper._metadata.update(metadata_batch) - completed |= batchable - - if len(completed) == 0 and len(batchable) == 0: - # remaining must be non-empty at this point - names = ", ".join([P.__name__ for P in remaining]) - raise MetadataException(f"Detected circular dependencies in {names}") - - remaining -= completed diff --git a/libcst/metadata/base_provider.py b/libcst/metadata/base_provider.py index e4950187..3cff524e 100644 --- a/libcst/metadata/base_provider.py +++ b/libcst/metadata/base_provider.py @@ -5,17 +5,7 @@ # pyre-strict from types import MappingProxyType -from typing import ( - TYPE_CHECKING, - Any, - Generic, - Iterable, - Mapping, - MutableMapping, - Type, - TypeVar, - cast, -) +from typing import TYPE_CHECKING, Generic, Mapping, MutableMapping, Type, TypeVar, cast from libcst._batched_visitor import BatchableCSTVisitor from libcst._metadata_dependent import ( @@ -144,18 +134,3 @@ class BatchableMetadataProvider( implementation should be provided in _gen_impl. """ pass - - -def _gen_batchable( - wrapper: "MetadataWrapper", - # pyre-fixme[2]: Parameter `providers` must have a type that does not contain `Any` - providers: Iterable[BatchableMetadataProvider[Any]], -) -> Mapping[ProviderT, Mapping["CSTNode", object]]: - """ - Returns map of metadata mappings from resolving ``providers`` on ``wrapper``. - """ - wrapper.visit_batched(providers) - - # Make immutable metadata mapping - # pyre-ignore[7] - return {type(p): MappingProxyType(dict(p._computed)) for p in providers} diff --git a/libcst/metadata/tests/test_base_provider.py b/libcst/metadata/tests/test_base_provider.py index 0a38ffa5..a1c92c51 100644 --- a/libcst/metadata/tests/test_base_provider.py +++ b/libcst/metadata/tests/test_base_provider.py @@ -13,7 +13,7 @@ from libcst.metadata import ( MetadataWrapper, VisitorMetadataProvider, ) -from libcst.metadata.base_provider import _gen_batchable +from libcst.metadata.wrapper import _gen_batchable from libcst.testing.utils import UnitTest diff --git a/libcst/metadata/wrapper.py b/libcst/metadata/wrapper.py index 23a9cb73..bfaa2958 100644 --- a/libcst/metadata/wrapper.py +++ b/libcst/metadata/wrapper.py @@ -7,12 +7,15 @@ import textwrap from contextlib import ExitStack +from types import MappingProxyType from typing import ( TYPE_CHECKING, + Any, Collection, Iterable, Mapping, MutableMapping, + MutableSet, Optional, Type, TypeVar, @@ -20,7 +23,8 @@ from typing import ( ) from libcst._batched_visitor import BatchableCSTVisitor, VisitorMethod, visit_batched -from libcst.metadata._resolver import _resolve_impl +from libcst._exceptions import MetadataException +from libcst.metadata.base_provider import BatchableMetadataProvider if TYPE_CHECKING: @@ -36,6 +40,68 @@ if TYPE_CHECKING: _T = TypeVar("_T") +def _gen_batchable( + wrapper: "MetadataWrapper", + # pyre-fixme[2]: Parameter `providers` must have a type that does not contain `Any` + providers: Iterable[BatchableMetadataProvider[Any]], +) -> Mapping["ProviderT", Mapping["CSTNode", object]]: + """ + Returns map of metadata mappings from resolving ``providers`` on ``wrapper``. + """ + wrapper.visit_batched(providers) + + # Make immutable metadata mapping + # pyre-ignore[7] + return {type(p): MappingProxyType(dict(p._computed)) for p in providers} + + +def _gather_providers( + providers: Collection["ProviderT"], gathered: MutableSet["ProviderT"] +) -> MutableSet["ProviderT"]: + """ + Recursively gathers all the given providers and their dependencies. + """ + for P in providers: + if P not in gathered: + gathered.add(P) + _gather_providers(P.METADATA_DEPENDENCIES, gathered) + return gathered + + +def _resolve_impl( + wrapper: "MetadataWrapper", providers: Collection["ProviderT"] +) -> None: + """ + Updates the _metadata map on wrapper with metadata from the given providers + as well as their dependencies. + """ + providers = set(providers) - set(wrapper._metadata.keys()) + remaining = _gather_providers(providers, set()) + + completed = set() + while len(remaining) > 0: + batchable = set() + + for P in remaining: + if set(P.METADATA_DEPENDENCIES).issubset(completed): + if issubclass(P, BatchableMetadataProvider): + batchable.add(P) + else: + wrapper._metadata[P] = P()._gen(wrapper) + completed.add(P) + + metadata_batch = _gen_batchable(wrapper, [p() for p in batchable]) + wrapper._metadata.update(metadata_batch) + completed |= batchable + + if len(completed) == 0 and len(batchable) == 0: + # remaining must be non-empty at this point + names = ", ".join([P.__name__ for P in remaining]) + raise MetadataException(f"Detected circular dependencies in {names}") + + remaining -= completed + + class MetadataWrapper: """ A wrapper around a :class:`~libcst.Module` that stores associated metadata