Add new dependencies and update existing packages in uv.lock
- Added `certifi` version 2026.4.22 and `charset-normalizer` version 3.4.7 with multiple wheel options. - Introduced `idna` version 3.14 and `prettytable` version 3.17.0 with their respective wheel files. - Updated `requests` to version 2.34.0, including its dependencies. - Added `urllib3` version 2.7.0 and `wcwidth` version 0.7.0 with their wheel files. - Updated `cli` package metadata to include new dependencies: `prettytable` and `requests`.
This commit is contained in:
+136
@@ -0,0 +1,136 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
class Config:
|
||||
def __init__(self, file_path: str | Path | None = None) -> None:
|
||||
default_path = Path.home() / ".config" / "rs-cli" / "config.json"
|
||||
self.file_path = Path(file_path).expanduser() if file_path else default_path
|
||||
self.data: dict[str, Any] = {}
|
||||
|
||||
def load(self) -> dict[str, Any]:
|
||||
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if not self.file_path.exists():
|
||||
self.data = {}
|
||||
self.save()
|
||||
return self.data
|
||||
|
||||
content = self.file_path.read_text(encoding="utf-8").strip()
|
||||
if not content:
|
||||
self.data = {}
|
||||
self.save()
|
||||
return self.data
|
||||
|
||||
parsed = json.loads(content)
|
||||
if not isinstance(parsed, dict):
|
||||
raise ValueError("El archivo de configuracion debe contener un objeto JSON.")
|
||||
|
||||
self.data = parsed
|
||||
return self.data
|
||||
|
||||
def save(self) -> None:
|
||||
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.file_path.write_text(
|
||||
json.dumps(self.data, indent=2, ensure_ascii=False) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def get(self, path: str, default: Any = None) -> Any:
|
||||
tokens = self._parse_path(path)
|
||||
current: Any = self.data
|
||||
|
||||
for token in tokens:
|
||||
if isinstance(token, str):
|
||||
if not isinstance(current, dict) or token not in current:
|
||||
return default
|
||||
current = current[token]
|
||||
continue
|
||||
|
||||
if not isinstance(current, list) or token >= len(current):
|
||||
return default
|
||||
current = current[token]
|
||||
|
||||
return current
|
||||
|
||||
def set(self, path: str, value: Any) -> None:
|
||||
tokens = self._parse_path(path)
|
||||
current: Any = self.data
|
||||
|
||||
for idx, token in enumerate(tokens):
|
||||
is_last = idx == len(tokens) - 1
|
||||
next_token = None if is_last else tokens[idx + 1]
|
||||
|
||||
if isinstance(token, str):
|
||||
if not isinstance(current, dict):
|
||||
raise TypeError(f"No se puede usar clave '{token}' en un nodo no-dict.")
|
||||
|
||||
if is_last:
|
||||
current[token] = value
|
||||
break
|
||||
|
||||
expected_type = list if isinstance(next_token, int) else dict
|
||||
if token not in current or current[token] is None:
|
||||
current[token] = [] if expected_type is list else {}
|
||||
elif not isinstance(current[token], expected_type):
|
||||
current[token] = [] if expected_type is list else {}
|
||||
|
||||
current = current[token]
|
||||
continue
|
||||
|
||||
if not isinstance(current, list):
|
||||
raise TypeError(f"No se puede usar indice [{token}] en un nodo no-list.")
|
||||
|
||||
while len(current) <= token:
|
||||
current.append(None)
|
||||
|
||||
if is_last:
|
||||
current[token] = value
|
||||
break
|
||||
|
||||
expected_type = list if isinstance(next_token, int) else dict
|
||||
if current[token] is None or not isinstance(current[token], expected_type):
|
||||
current[token] = [] if expected_type is list else {}
|
||||
|
||||
current = current[token]
|
||||
|
||||
self.save()
|
||||
|
||||
def _parse_path(self, path: str) -> list[str | int]:
|
||||
if not path or not isinstance(path, str):
|
||||
raise ValueError("La ruta no puede estar vacia.")
|
||||
|
||||
tokens: list[str | int] = []
|
||||
|
||||
for segment in path.split("."):
|
||||
if not segment:
|
||||
raise ValueError(f"Ruta invalida: '{path}'")
|
||||
|
||||
index = 0
|
||||
if segment[0] != "[":
|
||||
match = re.match(r"[^\[\]]+", segment)
|
||||
if not match:
|
||||
raise ValueError(f"Ruta invalida: '{path}'")
|
||||
key = match.group(0)
|
||||
tokens.append(key)
|
||||
index = len(key)
|
||||
|
||||
while index < len(segment):
|
||||
if segment[index] != "[":
|
||||
raise ValueError(f"Ruta invalida: '{path}'")
|
||||
end = segment.find("]", index)
|
||||
if end == -1:
|
||||
raise ValueError(f"Ruta invalida: '{path}'")
|
||||
|
||||
raw_index = segment[index + 1 : end]
|
||||
if not raw_index.isdigit():
|
||||
raise ValueError(f"Indice invalido en ruta: '{path}'")
|
||||
|
||||
tokens.append(int(raw_index))
|
||||
index = end + 1
|
||||
|
||||
return tokens
|
||||
Reference in New Issue
Block a user