updates
This commit is contained in:
239
Backend/venv/lib/python3.12/site-packages/safety/tool/uv/main.py
Normal file
239
Backend/venv/lib/python3.12/site-packages/safety/tool/uv/main.py
Normal file
@@ -0,0 +1,239 @@
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
from typing import Any, Dict, Optional
|
||||
import tomlkit
|
||||
import typer
|
||||
|
||||
from rich.console import Console
|
||||
from safety.console import main_console
|
||||
from safety.tool.auth import build_index_url
|
||||
from safety.tool.constants import (
|
||||
PYPI_ORGANIZATION_REPOSITORY_URL,
|
||||
PYPI_PUBLIC_REPOSITORY_URL,
|
||||
PYPI_PROJECT_REPOSITORY_URL,
|
||||
)
|
||||
from safety.utils.pyapp_utils import get_path
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def backup_file(path: Path) -> None:
|
||||
"""
|
||||
Create backup of file if it exists
|
||||
"""
|
||||
if path.exists():
|
||||
backup_path = path.with_name(f"{path.name}.backup")
|
||||
shutil.copy2(path, backup_path)
|
||||
|
||||
|
||||
class Uv:
|
||||
@classmethod
|
||||
def is_installed(cls) -> bool:
|
||||
"""
|
||||
Checks if the UV program is installed
|
||||
|
||||
Returns:
|
||||
True if UV is installed on system, or false otherwise
|
||||
"""
|
||||
return shutil.which("uv", path=get_path()) is not None
|
||||
|
||||
@classmethod
|
||||
def is_uv_project_file(cls, file: Path) -> bool:
|
||||
try:
|
||||
cfg = tomllib.loads(file.read_text())
|
||||
return (
|
||||
cfg.get("tool", {}).get("uv") is not None
|
||||
or (file.parent / "uv.lock").exists()
|
||||
)
|
||||
except (IOError, ValueError):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def configure_pyproject(
|
||||
cls,
|
||||
file: Path,
|
||||
org_slug: Optional[str],
|
||||
project_id: Optional[str] = None,
|
||||
console: Console = main_console,
|
||||
) -> Optional[Path]:
|
||||
"""
|
||||
Configures index url for specified pyproject.toml file.
|
||||
|
||||
Args:
|
||||
file (Path): Path to pyproject.toml file.
|
||||
org_slug (Optional[str]): Organization slug.
|
||||
project_id (Optional[str]): Project ID.
|
||||
console (Console): Console instance.
|
||||
"""
|
||||
if not cls.is_installed():
|
||||
logger.error("UV is not installed.")
|
||||
return None
|
||||
|
||||
repository_url = (
|
||||
PYPI_PROJECT_REPOSITORY_URL.format(org_slug, project_id)
|
||||
if project_id and org_slug
|
||||
else (
|
||||
PYPI_ORGANIZATION_REPOSITORY_URL.format(org_slug)
|
||||
if org_slug
|
||||
else PYPI_PUBLIC_REPOSITORY_URL
|
||||
)
|
||||
)
|
||||
try:
|
||||
content = file.read_text()
|
||||
doc: Dict[str, Any] = tomlkit.loads(content)
|
||||
|
||||
if "tool" not in doc:
|
||||
doc["tool"] = tomlkit.table()
|
||||
if "uv" not in doc["tool"]: # type: ignore
|
||||
doc["tool"]["uv"] = tomlkit.table() # type: ignore
|
||||
if "index" not in doc["tool"]["uv"]: # type: ignore
|
||||
doc["tool"]["uv"]["index"] = tomlkit.aot() # type: ignore
|
||||
|
||||
index_container = doc["tool"]["uv"] # type: ignore
|
||||
cls.filter_out_safety_index(index_container)
|
||||
|
||||
safety_index = {
|
||||
"name": "safety",
|
||||
"url": repository_url,
|
||||
# In UV default:
|
||||
# True = lowest priority
|
||||
# False = highest priority
|
||||
"default": False,
|
||||
}
|
||||
non_safety_indexes = (
|
||||
doc.get("tool", {}).get("uv", {}).get("index", tomlkit.aot())
|
||||
)
|
||||
|
||||
# Add safety index as first priority
|
||||
index_container["index"] = tomlkit.aot() # type: ignore
|
||||
index_container["index"].append(safety_index) # type: ignore
|
||||
index_container["index"].extend(non_safety_indexes) # type: ignore
|
||||
|
||||
# Write back to file
|
||||
file.write_text(tomlkit.dumps(doc))
|
||||
return file
|
||||
|
||||
except (IOError, ValueError, Exception) as e:
|
||||
logger.error(f"Failed to configure {file} file: {e}")
|
||||
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_user_config_path(cls) -> Path:
|
||||
"""
|
||||
Returns the path to the user config file for UV.
|
||||
|
||||
This logic is based on the uv documentation:
|
||||
https://docs.astral.sh/uv/configuration/files/
|
||||
|
||||
"uv will also discover user-level configuration at
|
||||
~/.config/uv/uv.toml (or $XDG_CONFIG_HOME/uv/uv.toml) on macOS and Linux,
|
||||
or %APPDATA%\\uv\\uv.toml on Windows; ..."
|
||||
|
||||
Returns:
|
||||
Path: The path to the user config file.
|
||||
"""
|
||||
if sys.platform == "win32":
|
||||
return Path(os.environ.get("APPDATA", ""), "uv", "uv.toml")
|
||||
else:
|
||||
xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
|
||||
if xdg_config_home:
|
||||
return Path(xdg_config_home, "uv", "uv.toml")
|
||||
else:
|
||||
return Path(Path.home(), ".config", "uv", "uv.toml")
|
||||
|
||||
@classmethod
|
||||
def filter_out_safety_index(cls, index_container: Any):
|
||||
if "index" not in index_container:
|
||||
return
|
||||
|
||||
indexes = list(index_container["index"])
|
||||
index_container["index"] = tomlkit.aot()
|
||||
|
||||
for index in indexes:
|
||||
index_url = index.get("url", "")
|
||||
|
||||
if ".safetycli.com" in index_url:
|
||||
continue
|
||||
|
||||
index_container["index"].append(index)
|
||||
|
||||
@classmethod
|
||||
def configure_system(
|
||||
cls, org_slug: Optional[str], console: Console = main_console
|
||||
) -> Optional[Path]:
|
||||
"""
|
||||
Configures UV system to use to Safety index url.
|
||||
"""
|
||||
try:
|
||||
repository_url = (
|
||||
PYPI_ORGANIZATION_REPOSITORY_URL.format(org_slug)
|
||||
if org_slug
|
||||
else PYPI_PUBLIC_REPOSITORY_URL
|
||||
)
|
||||
|
||||
user_config_path = cls.get_user_config_path()
|
||||
|
||||
if not user_config_path.exists():
|
||||
user_config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
content = ""
|
||||
else:
|
||||
backup_file(user_config_path)
|
||||
content = user_config_path.read_text()
|
||||
|
||||
doc = tomlkit.loads(content)
|
||||
if "index" not in doc:
|
||||
doc["index"] = tomlkit.aot()
|
||||
cls.filter_out_safety_index(index_container=doc)
|
||||
|
||||
safety_index = tomlkit.aot()
|
||||
safety_index.append(
|
||||
{
|
||||
"name": "safety",
|
||||
"url": repository_url,
|
||||
# In UV default:
|
||||
# True = lowest priority
|
||||
# False = highest priority
|
||||
"default": False,
|
||||
}
|
||||
)
|
||||
|
||||
non_safety_indexes = doc.get("index", tomlkit.aot())
|
||||
|
||||
# Add safety index as first priority
|
||||
doc["index"] = tomlkit.aot()
|
||||
doc.append("index", safety_index)
|
||||
doc.append("index", non_safety_indexes)
|
||||
|
||||
user_config_path.write_text(tomlkit.dumps(doc))
|
||||
return user_config_path
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to configure UV system: {e}")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def reset_system(cls, console: Console = main_console):
|
||||
try:
|
||||
user_config_path = cls.get_user_config_path()
|
||||
if user_config_path.exists():
|
||||
backup_file(user_config_path)
|
||||
content = user_config_path.read_text()
|
||||
doc = tomlkit.loads(content)
|
||||
cls.filter_out_safety_index(index_container=doc)
|
||||
user_config_path.write_text(tomlkit.dumps(doc))
|
||||
except Exception as e:
|
||||
msg = "Failed to reset UV global settings"
|
||||
logger.error(f"{msg}: {e}")
|
||||
|
||||
@classmethod
|
||||
def build_index_url(cls, ctx: typer.Context, index_url: Optional[str]) -> str:
|
||||
return build_index_url(ctx, index_url, "pypi")
|
||||
Reference in New Issue
Block a user