"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "client/configuration.py" between
pyre-check-0.0.53.tar.gz and pyre-check-0.0.54.tar.gz

About: Pyre is a performant type checker for Python (ships with Pysa, a security focused static analysis tool).

configuration.py  (pyre-check-0.0.53):configuration.py  (pyre-check-0.0.54)
skipping to change at line 159 skipping to change at line 159
Consume a key from the configuration. When a key is consumed, it Consume a key from the configuration. When a key is consumed, it
is removed from the configuration. is removed from the configuration.
If not found, the default is returned. If the current value is not If not found, the default is returned. If the current value is not
None, it will be returned instead, but the key will still be None, it will be returned instead, but the key will still be
considered consumed. considered consumed.
""" """
value = self._configuration.pop(key, default) value = self._configuration.pop(key, default)
if raise_on_override and current and value: if raise_on_override and current and value:
raise EnvironmentException( raise InvalidConfiguration(
f"Configuration file may not override `{key}` field." f"Configuration file may not override `{key}` field."
) )
if current: if current:
return current return current
if value and print_on_success: if value and print_on_success:
LOG.debug("Found %s: `%s`", key, ", ".join(value)) LOG.debug("Found %s: `%s`", key, ", ".join(value))
if value and key in self._deprecated: if value and key in self._deprecated:
LOG.warning( LOG.warning(
"Configuration file uses deprecated item `%s`: " "Configuration file uses deprecated item `%s`: "
"please migrate to its replacement `%s`", "please migrate to its replacement `%s`",
skipping to change at line 238 skipping to change at line 238
) )
self._version_hash: Optional[str] = None self._version_hash: Optional[str] = None
self._binary: Optional[str] = None self._binary: Optional[str] = None
self._typeshed: Optional[str] = None self._typeshed: Optional[str] = None
self._buck_builder_binary: Optional[str] = None self._buck_builder_binary: Optional[str] = None
self.strict: bool = strict self.strict: bool = strict
self._use_buck_builder: Optional[bool] = use_buck_builder self._use_buck_builder: Optional[bool] = use_buck_builder
self._use_buck_source_database: Optional[bool] = use_buck_source_databas e self._use_buck_source_database: Optional[bool] = use_buck_source_databas e
self.ignore_infer: List[str] = [] self.ignore_infer: List[str] = []
self.do_not_ignore_errors_in: List[str] = []
self._search_path: List[SearchPathElement] = [] self._search_path: List[SearchPathElement] = []
if search_path: if search_path:
search_path_elements = [ search_path_elements = [
SearchPathElement.expand(path, project_root=project_root) SearchPathElement.expand(path, project_root=project_root)
for path in search_path for path in search_path
] ]
self._search_path.extend(search_path_elements) self._search_path.extend(search_path_elements)
# We will extend the search path further, with the config file # We will extend the search path further, with the config file
# items, inside _read(). # items, inside _read().
skipping to change at line 264 skipping to change at line 265
if buck_builder_binary: if buck_builder_binary:
self._buck_builder_binary = buck_builder_binary self._buck_builder_binary = buck_builder_binary
self.excludes: List[str] = [] self.excludes: List[str] = []
if excludes: if excludes:
self.excludes.extend(excludes) self.excludes.extend(excludes)
if local_root: if local_root:
self._check_read_local_configuration(local_root) self._check_read_local_configuration(local_root)
self.ignore_all_errors.append(os.path.abspath(self.log_directory))
self.autocomplete = False self.autocomplete = False
self.other_critical_files: List[str] = [] self.other_critical_files: List[str] = []
project_configuration = os.path.join(project_root, CONFIGURATION_FILE) project_configuration = os.path.join(project_root, CONFIGURATION_FILE)
# Order matters. The values will only be updated if a field is None. # Order matters. The values will only be updated if a field is None.
self._read(project_configuration) self._read(project_configuration)
self._override_version_hash() self._override_version_hash()
skipping to change at line 313 skipping to change at line 313
strict=arguments.strict, strict=arguments.strict,
logger=arguments.logger, logger=arguments.logger,
formatter=arguments.formatter, formatter=arguments.formatter,
dot_pyre_directory=( dot_pyre_directory=(
arguments.dot_pyre_directory or global_root / LOG_DIRECTORY arguments.dot_pyre_directory or global_root / LOG_DIRECTORY
), ),
use_buck_source_database=arguments.use_buck_source_database, use_buck_source_database=arguments.use_buck_source_database,
) )
def _validate(self) -> None: def _validate(self) -> None:
try: def is_list_of_strings(list):
if len(list) == 0:
return True
return not isinstance(list, str) and all(
isinstance(element, str) for element in list
)
def is_list_of_strings(list): if not is_list_of_strings(self.source_directories) or not is_list_of_str
if len(list) == 0: ings(
return True self.targets
return not isinstance(list, str) and all( ):
isinstance(element, str) for element in list raise InvalidConfiguration(
) "`target` and `source_directories` fields must be lists of " "st
rings."
)
if not is_list_of_strings( if not is_list_of_strings(self.ignore_all_errors):
self.source_directories raise InvalidConfiguration(
) or not is_list_of_strings(self.targets): "`ignore_all_errors` field must be a list of strings."
raise InvalidConfiguration( )
"`target` and `source_directories` fields must be lists of "
"strings."
)
if not is_list_of_strings(self.ignore_all_errors): if not is_list_of_strings(self.ignore_infer):
raise InvalidConfiguration( raise InvalidConfiguration(
"`ignore_all_errors` field must be a list of strings." "`ignore_infer` field must be a list of strings."
) )
if not is_list_of_strings(self.ignore_infer): if not is_list_of_strings(self.extensions):
raise InvalidConfiguration( raise InvalidConfiguration("`extensions` field must be a list of str
"`ignore_infer` field must be a list of strings." ings.")
) if not all(
extension.startswith(".") or not extension for extension in self.ext
ensions
):
raise InvalidConfiguration(
"`extensions` must only contain strings formatted as `.EXT`"
)
if not is_list_of_strings(self.extensions): if not os.path.exists(self.binary):
raise InvalidConfiguration( raise InvalidConfiguration(f"Binary at `{self.binary}` does not exis
"`extensions` field must be a list of strings." t.")
)
if not all(
extension.startswith(".") or not extension
for extension in self.extensions
):
raise InvalidConfiguration(
"`extensions` must only contain strings formatted as `.EXT`"
)
if not os.path.exists(self.binary): if self.number_of_workers < 1:
raise InvalidConfiguration(f"Binary at `{self.binary}` does not raise InvalidConfiguration("Number of workers must be greater than 0
exist.") .")
if self.number_of_workers < 1: # Validate typeshed path and sub-elements.
raise InvalidConfiguration("Number of workers must be greater th assert_readable_directory_in_configuration(self.typeshed, field_name="ty
an 0.") peshed")
# Validate typeshed path and sub-elements. # A courtesy warning since we have changed default behaviour.
assert_readable_directory_in_configuration( if self._typeshed_has_obsolete_value():
self.typeshed, field_name="typeshed" LOG.warning(
f"It appears that `{self.typeshed}` points at a `stdlib` "
"directory. Please note that the `typeshed` configuration must "
"point to the root of the `typeshed` directory."
) )
# A courtesy warning since we have changed default behaviour. expanded_ignore_paths = []
if self._typeshed_has_obsolete_value(): for path in self.ignore_all_errors:
LOG.warning( expanded = glob.glob(path)
f"It appears that `{self.typeshed}` points at a `stdlib` " if not expanded:
"directory. Please note that the `typeshed` configuration mu expanded_ignore_paths.append(path)
st " else:
"point to the root of the `typeshed` directory." expanded_ignore_paths += expanded
) self.ignore_all_errors = expanded_ignore_paths
expanded_ignore_paths = []
for path in self.ignore_all_errors:
expanded = glob.glob(path)
if not expanded:
expanded_ignore_paths.append(path)
else:
expanded_ignore_paths += expanded
self.ignore_all_errors = expanded_ignore_paths
non_existent_ignore_paths = [ non_existent_ignore_paths = [
path for path in self.ignore_all_errors if not os.path.exists(pa path for path in self.ignore_all_errors if not os.path.exists(path)
th) ]
if non_existent_ignore_paths:
LOG.warning(
"Nonexistent paths passed in to `ignore_all_errors`: "
f"`{non_existent_ignore_paths}`"
)
self.ignore_all_errors = [
path
for path in self.ignore_all_errors
if path not in non_existent_ignore_paths
] ]
if non_existent_ignore_paths:
LOG.warning(
"Nonexistent paths passed in to `ignore_all_errors`: "
f"`{non_existent_ignore_paths}`"
)
self.ignore_all_errors = [
path
for path in self.ignore_all_errors
if path not in non_existent_ignore_paths
]
non_existent_infer_paths = [ non_existent_infer_paths = [
path for path in self.ignore_infer if not os.path.exists(path) path for path in self.ignore_infer if not os.path.exists(path)
]
if non_existent_infer_paths:
LOG.warning(
"Nonexistent paths passed in to `ignore_infer`: "
f"`{non_existent_infer_paths}`"
)
self.ignore_infer = [
path
for path in self.ignore_infer
if path not in non_existent_infer_paths
] ]
if non_existent_infer_paths:
LOG.warning(
"Nonexistent paths passed in to `ignore_infer`: "
f"`{non_existent_infer_paths}`"
)
self.ignore_infer = [
path
for path in self.ignore_infer
if path not in non_existent_infer_paths
]
for typeshed_subdirectory_name in ["stdlib", "third_party"]:
typeshed_subdirectory = os.path.join(
self.typeshed, typeshed_subdirectory_name
)
assert_readable_directory_in_configuration(typeshed_subdirectory
)
for typeshed_version_directory_name in os.listdir(
typeshed_subdirectory
):
if not typeshed_version_directory_name[0].isdigit():
raise InvalidConfiguration(
"Directories inside `typeshed` must only contain "
"second-level subdirectories starting with "
"a version number."
)
typeshed_version_directory = os.path.join(
typeshed_subdirectory, typeshed_version_directory_name
)
assert_readable_directory_in_configuration(
typeshed_version_directory
)
# Validate elements of the search path. for typeshed_subdirectory_name in ["stdlib", "third_party"]:
for element in self._search_path: typeshed_subdirectory = os.path.join(
assert_readable_directory_in_configuration( self.typeshed, typeshed_subdirectory_name
element.path(), field_name="search_path" )
assert_readable_directory_in_configuration(typeshed_subdirectory)
for typeshed_version_directory_name in os.listdir(typeshed_subdirect
ory):
if not typeshed_version_directory_name[0].isdigit():
raise InvalidConfiguration(
"Directories inside `typeshed` must only contain "
"second-level subdirectories starting with "
"a version number."
)
typeshed_version_directory = os.path.join(
typeshed_subdirectory, typeshed_version_directory_name
) )
assert_readable_directory_in_configuration(typeshed_version_dire ctory)
if not is_list_of_strings(self.other_critical_files): # Validate elements of the search path.
raise InvalidConfiguration( for element in self._search_path:
"`critical_files` field must be a list of strings." assert_readable_directory_in_configuration(
) element.path(), field_name="search_path"
except InvalidConfiguration as error: )
raise EnvironmentException(str(error))
if not is_list_of_strings(self.other_critical_files):
raise InvalidConfiguration(
"`critical_files` field must be a list of strings."
)
if not is_list_of_strings(self.do_not_ignore_errors_in):
raise InvalidConfiguration(
"`do_not_ignore_errors_in` field must be a list of strings."
)
for directory_name in self.do_not_ignore_errors_in:
assert_readable_directory_in_configuration(directory_name)
@property @property
def version_hash(self) -> str: def version_hash(self) -> str:
return self._version_hash or "unversioned" return self._version_hash or "unversioned"
@property @property
def binary(self) -> str: def binary(self) -> str:
binary = self._binary binary = self._binary
if not binary: if not binary:
raise InvalidConfiguration("No binary specified.") raise InvalidConfiguration("No binary specified.")
skipping to change at line 519 skipping to change at line 512
buck_builder_binary=self._buck_builder_binary, buck_builder_binary=self._buck_builder_binary,
excludes=self.excludes, excludes=self.excludes,
logger=self.logger, logger=self.logger,
formatter=self.formatter, formatter=self.formatter,
dot_pyre_directory=self.dot_pyre_directory, dot_pyre_directory=self.dot_pyre_directory,
) )
paths_to_ignore = list(local_root.parents) + [local_root] paths_to_ignore = list(local_root.parents) + [local_root]
for ignore_element in parent_local_configuration.ignore_all_errors: for ignore_element in parent_local_configuration.ignore_all_errors:
if Path(ignore_element).resolve() in paths_to_ignore: if Path(ignore_element).resolve() in paths_to_ignore:
excluded_from_parent = True excluded_from_parent = True
except EnvironmentException as error: except InvalidConfiguration as error:
parent_error = error parent_error = error
if not excluded_from_parent: if not excluded_from_parent:
relative_path = str(local_root.relative_to(parent_local_root)) relative_path = str(local_root.relative_to(parent_local_root))
error_message = ( error_message = (
"Local configuration is nested under another local configuration at " "Local configuration is nested under another local configuration at "
f"`{parent_local_root}`.\nPlease add `{relative_path}` to the " f"`{parent_local_root}`.\nPlease add `{relative_path}` to the "
"`ignore_all_errors` field of the parent, or combine the sources " "`ignore_all_errors` field of the parent, or combine the sources "
"into a single configuration, or split the parent configuration to " "into a single configuration, or split the parent configuration to "
"avoid inconsistent errors." "avoid inconsistent errors."
) )
raise EnvironmentException(error_message) raise InvalidConfiguration(error_message)
elif parent_error: elif parent_error:
raise EnvironmentException(parent_error) raise InvalidConfiguration(str(parent_error))
def _check_read_local_configuration(self, path: str) -> None: def _check_read_local_configuration(self, path: str) -> None:
if not os.path.exists(path): if not os.path.exists(path):
raise EnvironmentException( raise InvalidConfiguration(
f"Local configuration path `{path}` does not exist." f"Local configuration path `{path}` does not exist."
) )
local_configuration = os.path.join(path, LOCAL_CONFIGURATION_FILE) local_configuration = os.path.join(path, LOCAL_CONFIGURATION_FILE)
if not os.path.exists(local_configuration): if not os.path.exists(local_configuration):
raise EnvironmentException( raise InvalidConfiguration(
f"Local configuration directory `{path}` does not contain " f"Local configuration directory `{path}` does not contain "
f"a `{LOCAL_CONFIGURATION_FILE}` file." f"a `{LOCAL_CONFIGURATION_FILE}` file."
) )
self._check_nested_configurations(path) self._check_nested_configurations(path)
self._read(local_configuration) self._read(local_configuration)
if not self.source_directories and not self.targets: if not self.source_directories and not self.targets:
raise EnvironmentException( raise InvalidConfiguration(
f"Local configuration `{local_configuration}` does not specify " f"Local configuration `{local_configuration}` does not specify "
" any sources to type check." " any sources to type check."
) )
def _read(self, path: str) -> None: def _read(self, path: str) -> None:
try: try:
with open(path) as file: with open(path) as file:
LOG.debug("Reading configuration `%s`...", path) LOG.debug("Reading configuration `%s`...", path)
configuration_directory = os.path.dirname(os.path.realpath(path) ) configuration_directory = os.path.dirname(os.path.realpath(path) )
configuration = _ConfigurationFile(file) configuration = _ConfigurationFile(file)
skipping to change at line 686 skipping to change at line 679
) )
if self._use_buck_source_database is None: if self._use_buck_source_database is None:
self._use_buck_source_database = use_buck_source_database self._use_buck_source_database = use_buck_source_database
self.autocomplete = configuration.consume("autocomplete", defaul t=False) self.autocomplete = configuration.consume("autocomplete", defaul t=False)
self.other_critical_files = configuration.consume( self.other_critical_files = configuration.consume(
"critical_files", default=[] "critical_files", default=[]
) )
do_not_ignore_errors_in = configuration.consume(
"do_not_ignore_errors_in", default=[]
)
assert isinstance(do_not_ignore_errors_in, list)
self.do_not_ignore_errors_in.extend(do_not_ignore_errors_in)
# Warn on deprecated fields. # Warn on deprecated fields.
for deprecated_field in configuration._deprecated.keys(): for deprecated_field in configuration._deprecated.keys():
configuration.consume(deprecated_field) configuration.consume(deprecated_field)
# This block should be at the bottom to be effective. # This block should be at the bottom to be effective.
unused_keys = configuration.unused_keys() unused_keys = configuration.unused_keys()
if unused_keys: if unused_keys:
LOG.warning( LOG.warning(
"Some configuration items were not recognized in " "Some configuration items were not recognized in "
"`{}`: {}".format(path, ", ".join(unused_keys)) "`{}`: {}".format(path, ", ".join(unused_keys))
) )
self._expand_relative_paths(configuration_directory) self._expand_relative_paths(configuration_directory)
except IOError: except IOError:
# To avoid TOCTTOU bugs, handle IOErrors here silently. # To avoid TOCTTOU bugs, handle IOErrors here silently.
# We error elsewhere if there weren't enough parameters passed into pyre. # We error elsewhere if there weren't enough parameters passed into pyre.
self._expand_relative_paths(configuration_directory) self._expand_relative_paths(configuration_directory)
except json.JSONDecodeError as error: except json.JSONDecodeError as error:
raise EnvironmentException( raise InvalidConfiguration(
"Configuration file at `{}` is invalid: {}.".format(path, str(er ror)) "Configuration file at `{}` is invalid: {}.".format(path, str(er ror))
) )
def _expand_relative_paths(self, root: str) -> None: def _expand_relative_paths(self, root: str) -> None:
self.source_directories = [ self.source_directories = [
expand_relative_path(root, directory) expand_relative_path(root, directory)
for directory in self.source_directories for directory in self.source_directories
] ]
logger = self.logger logger = self.logger
skipping to change at line 745 skipping to change at line 744
self._typeshed = expand_relative_path(root, typeshed) self._typeshed = expand_relative_path(root, typeshed)
self.taint_models_path = [ self.taint_models_path = [
expand_relative_path(root, path) for path in self.taint_models_path expand_relative_path(root, path) for path in self.taint_models_path
] ]
self.other_critical_files = [ self.other_critical_files = [
expand_relative_path(root, path) for path in self.other_critical_fil es expand_relative_path(root, path) for path in self.other_critical_fil es
] ]
self.do_not_ignore_errors_in = [
expand_relative_path(root, path) for path in self.do_not_ignore_erro
rs_in
]
def _resolve_versioned_paths(self) -> None: def _resolve_versioned_paths(self) -> None:
version_hash = self.version_hash version_hash = self.version_hash
if not version_hash: if not version_hash:
return return
binary = self._binary binary = self._binary
if binary: if binary:
self._binary = binary.replace("%V", version_hash) self._binary = binary.replace("%V", version_hash)
typeshed = self._typeshed typeshed = self._typeshed
if typeshed: if typeshed:
 End of changes. 29 change blocks. 
125 lines changed or deleted 132 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)