eptm_dashboard/.venv/lib/python3.12/site-packages/reflex/utils/rename.py

169 lines
5.1 KiB
Python

"""This module provides utilities for renaming directories and files in a Reflex app."""
import re
import sys
from pathlib import Path
from reflex_base import constants
from reflex_base.config import get_config
from reflex_base.utils import console
from reflex.utils.misc import get_module_path
def rename_path_up_tree(full_path: str | Path, old_name: str, new_name: str) -> Path:
"""Rename all instances of `old_name` in the path (file and directories) to `new_name`.
The renaming stops when we reach the directory containing `rxconfig.py`.
Args:
full_path: The full path to start renaming from.
old_name: The name to be replaced.
new_name: The replacement name.
Returns:
The updated path after renaming.
"""
current_path = Path(full_path)
new_path = None
while True:
directory, base = current_path.parent, current_path.name
# Stop renaming when we reach the root dir (which contains rxconfig.py)
if current_path.is_dir() and (current_path / "rxconfig.py").exists():
new_path = current_path
break
if old_name == base.removesuffix(constants.Ext.PY):
new_base = base.replace(old_name, new_name)
new_path = directory / new_base
current_path.rename(new_path)
console.debug(f"Renamed {current_path} -> {new_path}")
current_path = new_path
else:
new_path = current_path
# Move up the directory tree
current_path = directory
return new_path
def rename_app(new_app_name: str, loglevel: constants.LogLevel):
"""Rename the app directory.
Args:
new_app_name: The new name for the app.
loglevel: The log level to use.
Raises:
SystemExit: If the command is not ran in the root dir or the app module cannot be imported.
"""
# Set the log level.
console.set_log_level(loglevel)
if not constants.Config.FILE.exists():
console.error(
"No rxconfig.py found. Make sure you are in the root directory of your app."
)
raise SystemExit(1)
sys.path.insert(0, str(Path.cwd()))
config = get_config()
module_path = get_module_path(config.module)
if module_path is None:
console.error(f"Could not find module {config.module}.")
raise SystemExit(1)
console.info(f"Renaming app directory to {new_app_name}.")
process_directory(
Path.cwd(),
config.app_name,
new_app_name,
exclude_dirs=[constants.Dirs.WEB, constants.Dirs.APP_ASSETS],
)
rename_path_up_tree(module_path, config.app_name, new_app_name)
console.success(f"App directory renamed to [bold]{new_app_name}[/bold].")
def rename_imports_and_app_name(file_path: str | Path, old_name: str, new_name: str):
"""Rename imports the file using string replacement as well as app_name in rxconfig.py.
Args:
file_path: The file to process.
old_name: The old name to replace.
new_name: The new name to use.
"""
file_path = Path(file_path)
content = file_path.read_text()
# Replace `from old_name.` or `from old_name` with `from new_name`
content = re.sub(
rf"\bfrom {re.escape(old_name)}(\b|\.|\s)",
lambda match: f"from {new_name}{match.group(1)}",
content,
)
# Replace `import old_name` with `import new_name`
content = re.sub(
rf"\bimport {re.escape(old_name)}\b",
f"import {new_name}",
content,
)
# Replace `app_name="old_name"` in rx.Config
content = re.sub(
rf'\bapp_name\s*=\s*["\']{re.escape(old_name)}["\']',
f'app_name="{new_name}"',
content,
)
# Replace positional argument `"old_name"` in rx.Config
content = re.sub(
rf'\brx\.Config\(\s*["\']{re.escape(old_name)}["\']',
f'rx.Config("{new_name}"',
content,
)
file_path.write_text(content)
def process_directory(
directory: str | Path,
old_name: str,
new_name: str,
exclude_dirs: list | None = None,
extensions: list | None = None,
):
"""Process files with specified extensions in a directory, excluding specified directories.
Args:
directory: The root directory to process.
old_name: The old name to replace.
new_name: The new name to use.
exclude_dirs: List of directory names to exclude. Defaults to None.
extensions: List of file extensions to process.
"""
exclude_dirs = exclude_dirs or []
extensions = extensions or [
constants.Ext.PY,
constants.Ext.MD,
] # include .md files, typically used in reflex-web.
extensions_set = {ext.lstrip(".") for ext in extensions}
directory = Path(directory)
root_exclude_dirs = {directory / exclude_dir for exclude_dir in exclude_dirs}
files = (
p.resolve()
for p in directory.glob("**/*")
if p.is_file() and p.suffix.lstrip(".") in extensions_set
)
for file_path in files:
if not any(
file_path.is_relative_to(exclude_dir) for exclude_dir in root_exclude_dirs
):
rename_imports_and_app_name(file_path, old_name, new_name)