client/commands/initialize_pysa.py (69 lines of code) (raw):
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import logging
import os
import subprocess
import sys
from pathlib import Path
from .. import log
from ..find_directories import find_taint_models_directory
from . import commands
LOG: logging.Logger = logging.getLogger(__name__)
class PysaInitializationError(Exception):
pass
def run() -> int:
try:
working_directory = Path(os.getcwd()).resolve()
# Check if venv is in working_directory
venv_path = (
# pyre-fixme[6]: Incompatible parameter type for `Path`, expected `str`
Path(os.environ.get("VIRTUAL_ENV")).resolve()
if os.environ.get("VIRTUAL_ENV", False)
else None
)
if venv_path is not None and str(working_directory) in str(
venv_path.parent.absolute()
):
raise PysaInitializationError(
"Can't use a virtual environment in the project directory."
" Please use one outside the project directory."
)
# Install dependencies
install_dependencies = log.get_yes_no_input(
"Would you like to install the project dependencies now?"
)
if install_dependencies:
requirements_file = "requirements.txt"
if not os.path.isfile(working_directory / requirements_file):
requirements_file = Path(
log.get_input(
f"requirements.txt file not found in `{working_directory}`"
" Please enter its location (eg: ./requirements-dev.txt): "
)
)
requirements_file = working_directory / requirements_file
subprocess.run(
[sys.executable, "-m", "pip", "install", "-r", requirements_file],
check=True,
)
else:
LOG.warning(
"You have chosen not to install dependencies."
" Please install dependencies before running Pysa to get best results."
)
run_infer = log.get_yes_no_input("Would you like to generate type annotations?")
if run_infer:
subprocess.run(["pyre", "infer", "-i"], check=True)
pyre_check_path = find_taint_models_directory()
if pyre_check_path and os.path.isdir(pyre_check_path / "pyre_check"):
pyre_check_path = pyre_check_path / "pyre_check"
LOG.info("Importing filters to sapp")
subprocess.run(["sapp", "filter", "import", pyre_check_path], check=True)
else:
LOG.warning(
"Couldn't infer filter directory, skipping filter import to sapp."
)
LOG.log(
log.SUCCESS,
"Successfully initialized an environemnt to run Pysa!\n"
+ " You can now run Pysa with `pyre analyze`.",
)
return commands.ExitCode.SUCCESS
except Exception as error:
LOG.error(f"Couldn't complete Pysa initialization:\n{error}")
return commands.ExitCode.FAILURE