in client/configuration.py [0:0]
def from_string(contents: str) -> "PartialConfiguration":
def is_list_of_string(elements: object) -> bool:
return isinstance(elements, list) and all(
isinstance(element, str) for element in elements
)
def ensure_option_type(
json: Dict[str, Any], name: str, expected_type: Type[T]
) -> Optional[T]:
result = json.pop(name, None)
if result is None:
return None
elif isinstance(result, expected_type):
return result
raise InvalidConfiguration(
f"Configuration `{name}` is expected to have type "
f"{expected_type} but got: `{json}`."
)
def ensure_optional_string_or_string_dict(
json: Dict[str, Any], name: str
) -> Optional[Union[Dict[str, str], str]]:
result = json.pop(name, None)
if result is None:
return None
elif isinstance(result, str):
return result
elif isinstance(result, Dict):
for value in result.values():
if not isinstance(value, str):
raise InvalidConfiguration(
f"Configuration `{name}` is expected to be a "
+ f"dict of strings but got `{json}`."
)
return result
raise InvalidConfiguration(
f"Configuration `{name}` is expected to be a string or a "
+ f"dict of strings but got `{json}`."
)
def ensure_optional_string_list(
json: Dict[str, Any], name: str
) -> Optional[List[str]]:
result = json.pop(name, None)
if result is None:
return None
elif is_list_of_string(result):
return result
raise InvalidConfiguration(
f"Configuration `{name}` is expected to be a list of "
+ f"strings but got `{json}`."
)
def ensure_string_list(
json: Dict[str, Any], name: str, allow_single_string: bool = False
) -> List[str]:
result = json.pop(name, [])
if allow_single_string and isinstance(result, str):
result = [result]
if is_list_of_string(result):
return result
raise InvalidConfiguration(
f"Configuration `{name}` is expected to be a list of "
+ f"strings but got `{json}`."
)
def ensure_list(json: Dict[str, Any], name: str) -> List[Any]:
result = json.pop(name, [])
if isinstance(result, list):
return result
raise InvalidConfiguration(
f"Configuration `{name}` is expected to be a list but got `{json}`."
)
try:
configuration_json = json.loads(contents)
dot_pyre_directory = ensure_option_type(
configuration_json, "dot_pyre_directory", str
)
search_path_json = configuration_json.pop("search_path", [])
if isinstance(search_path_json, list):
search_path = [
element
for json in search_path_json
for element in create_search_paths(
json, site_roots=get_site_roots()
)
]
else:
search_path = create_search_paths(
search_path_json, site_roots=get_site_roots()
)
python_version_json = configuration_json.pop("python_version", None)
if python_version_json is None:
python_version = None
elif isinstance(python_version_json, str):
python_version = PythonVersion.from_string(python_version_json)
else:
raise InvalidConfiguration(
"Expect python version to be a string but got"
+ f"'{python_version_json}'"
)
shared_memory_json = ensure_option_type(
configuration_json, "shared_memory", dict
)
if shared_memory_json is None:
shared_memory = SharedMemory()
else:
shared_memory = SharedMemory(
heap_size=ensure_option_type(shared_memory_json, "heap_size", int),
dependency_table_power=ensure_option_type(
shared_memory_json, "dependency_table_power", int
),
hash_table_power=ensure_option_type(
shared_memory_json, "hash_table_power", int
),
)
for unrecognized_key in shared_memory_json:
LOG.warning(f"Unrecognized configuration item: {unrecognized_key}")
source_directories_json = ensure_option_type(
configuration_json, "source_directories", list
)
if isinstance(source_directories_json, list):
source_directories = [
element
for json in source_directories_json
for element in create_search_paths(
json, site_roots=get_site_roots()
)
]
else:
source_directories = None
ide_features_json = ensure_option_type(
configuration_json, "ide_features", dict
)
if ide_features_json is None:
ide_features = None
else:
ide_features = IdeFeatures(
hover_enabled=ensure_option_type(
ide_features_json, "hover_enabled", bool
),
go_to_definition_enabled=ensure_option_type(
ide_features_json, "go_to_definition_enabled", bool
),
)
for unrecognized_key in ide_features_json:
LOG.warning(f"Unrecognized configuration item: {unrecognized_key}")
unwatched_dependency_json = ensure_option_type(
configuration_json, "unwatched_dependency", dict
)
if unwatched_dependency_json is None:
unwatched_dependency = None
else:
unwatched_dependency = UnwatchedDependency.from_json(
unwatched_dependency_json
)
partial_configuration = PartialConfiguration(
binary=ensure_option_type(configuration_json, "binary", str),
buck_mode=PlatformAware.from_json(
ensure_optional_string_or_string_dict(
configuration_json, "buck_mode"
),
"buck_mode",
),
disabled=ensure_option_type(configuration_json, "disabled", bool),
do_not_ignore_errors_in=ensure_string_list(
configuration_json, "do_not_ignore_errors_in"
),
dot_pyre_directory=Path(dot_pyre_directory)
if dot_pyre_directory is not None
else None,
excludes=ensure_string_list(
configuration_json, "exclude", allow_single_string=True
),
extensions=[
ExtensionElement.from_json(json)
for json in ensure_list(configuration_json, "extensions")
],
ide_features=ide_features,
ignore_all_errors=ensure_string_list(
configuration_json, "ignore_all_errors"
),
ignore_infer=ensure_string_list(configuration_json, "ignore_infer"),
isolation_prefix=ensure_option_type(
configuration_json, "isolation_prefix", str
),
logger=ensure_option_type(configuration_json, "logger", str),
number_of_workers=ensure_option_type(
configuration_json, "workers", int
),
oncall=ensure_option_type(configuration_json, "oncall", str),
other_critical_files=ensure_string_list(
configuration_json, "critical_files"
),
pysa_version_hash=ensure_option_type(
configuration_json, "pysa_version", str
),
python_version=python_version,
shared_memory=shared_memory,
search_path=search_path,
source_directories=source_directories,
strict=ensure_option_type(configuration_json, "strict", bool),
taint_models_path=ensure_string_list(
configuration_json, "taint_models_path", allow_single_string=True
),
targets=ensure_optional_string_list(configuration_json, "targets"),
typeshed=ensure_option_type(configuration_json, "typeshed", str),
unwatched_dependency=unwatched_dependency,
use_buck2=ensure_option_type(configuration_json, "use_buck2", bool),
version_hash=ensure_option_type(configuration_json, "version", str),
)
# Check for deprecated and unused keys
for (
deprecated_key,
replacement_key,
) in PartialConfiguration._get_depreacted_map().items():
if deprecated_key in configuration_json:
configuration_json.pop(deprecated_key)
LOG.warning(
f"Configuration file uses deprecated item `{deprecated_key}`. "
f"Please migrate to its replacement `{replacement_key}`"
)
extra_keys = PartialConfiguration._get_extra_keys()
for unrecognized_key in configuration_json:
if unrecognized_key not in extra_keys:
LOG.warning(f"Unrecognized configuration item: {unrecognized_key}")
return partial_configuration
except json.JSONDecodeError as error:
raise InvalidConfiguration(f"Invalid JSON file: {error}")