CLI script to maintain Chakra backed components in rx namespace in older apps (#2322)
This commit is contained in:
parent
ea2a5904f2
commit
a4ee985509
@ -100,6 +100,9 @@ def _init(
|
||||
# Migrate Pynecone projects to Reflex.
|
||||
prerequisites.migrate_to_reflex()
|
||||
|
||||
if prerequisites.should_show_rx_chakra_migration_instructions():
|
||||
prerequisites.show_rx_chakra_migration_instructions()
|
||||
|
||||
# Initialize the .gitignore.
|
||||
prerequisites.initialize_gitignore()
|
||||
|
||||
@ -336,6 +339,7 @@ def logout(
|
||||
|
||||
|
||||
db_cli = typer.Typer()
|
||||
script_cli = typer.Typer()
|
||||
|
||||
|
||||
def _skip_compile():
|
||||
@ -414,6 +418,17 @@ def makemigrations(
|
||||
)
|
||||
|
||||
|
||||
@script_cli.command(
|
||||
name="keep-chakra",
|
||||
help="Change all rx.<component> references to rx.chakra.<component>, to preserve Chakra UI usage.",
|
||||
)
|
||||
def keep_chakra():
|
||||
"""Change all rx.<component> references to rx.chakra.<component>, to preserve Chakra UI usage."""
|
||||
from reflex.utils import prerequisites
|
||||
|
||||
prerequisites.migrate_to_rx_chakra()
|
||||
|
||||
|
||||
@cli.command()
|
||||
def deploy(
|
||||
key: Optional[str] = typer.Option(
|
||||
@ -555,6 +570,7 @@ def demo(
|
||||
|
||||
|
||||
cli.add_typer(db_cli, name="db", help="Subcommands for managing the database schema.")
|
||||
cli.add_typer(script_cli, name="script", help="Subcommands running helper scripts.")
|
||||
cli.add_typer(
|
||||
deployments_cli,
|
||||
name="deployments",
|
||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import glob
|
||||
import importlib
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
@ -25,6 +26,7 @@ from alembic.util.exc import CommandError
|
||||
from packaging import version
|
||||
from redis.asyncio import Redis
|
||||
|
||||
import reflex
|
||||
from reflex import constants, model
|
||||
from reflex.compiler import templates
|
||||
from reflex.config import Config, get_config
|
||||
@ -938,6 +940,110 @@ def prompt_for_template() -> constants.Templates.Kind:
|
||||
return constants.Templates.Kind(template)
|
||||
|
||||
|
||||
def should_show_rx_chakra_migration_instructions() -> bool:
|
||||
"""Should we show the migration instructions for rx.chakra.* => rx.*?.
|
||||
|
||||
Returns:
|
||||
bool: True if we should show the migration instructions.
|
||||
"""
|
||||
if os.getenv("REFLEX_PROMPT_MIGRATE_TO_RX_CHAKRA") == "yes":
|
||||
return True
|
||||
|
||||
with open(constants.Dirs.REFLEX_JSON, "r") as f:
|
||||
data = json.load(f)
|
||||
existing_init_reflex_version = data.get("version", None)
|
||||
|
||||
if existing_init_reflex_version is None:
|
||||
# They clone a reflex app from git for the first time.
|
||||
# That app may or may not be 0.4 compatible.
|
||||
# So let's just show these instructions THIS TIME.
|
||||
return True
|
||||
|
||||
if constants.Reflex.VERSION < "0.4":
|
||||
return False
|
||||
else:
|
||||
return existing_init_reflex_version < "0.4"
|
||||
|
||||
|
||||
def show_rx_chakra_migration_instructions():
|
||||
"""Show the migration instructions for rx.chakra.* => rx.*."""
|
||||
console.log(
|
||||
"Prior to reflex 0.4.0, rx.* components are based on Chakra UI. They are now based on Radix UI. To stick to Chakra UI, use rx.chakra.*."
|
||||
)
|
||||
console.log("")
|
||||
console.log(
|
||||
"[bold]Run `reflex script keep-chakra` to automatically update your app."
|
||||
)
|
||||
console.log("")
|
||||
console.log("For more details, please see https://TODO") # TODO add link to docs
|
||||
|
||||
|
||||
def migrate_to_rx_chakra():
|
||||
"""Migrate rx.button => r.chakra.button, etc."""
|
||||
file_pattern = os.path.join(get_config().app_name, "**/*.py")
|
||||
file_list = glob.glob(file_pattern, recursive=True)
|
||||
|
||||
# Populate with all rx.<x> components that have been moved to rx.chakra.<x>
|
||||
patterns = {
|
||||
rf"\brx\.{name}\b": f"rx.chakra.{name}"
|
||||
for name in _get_rx_chakra_component_to_migrate()
|
||||
}
|
||||
|
||||
for file_path in file_list:
|
||||
with FileInput(file_path, inplace=True) as file:
|
||||
for _line_num, line in enumerate(file):
|
||||
for old, new in patterns.items():
|
||||
line = re.sub(old, new, line)
|
||||
print(line, end="")
|
||||
|
||||
|
||||
def _get_rx_chakra_component_to_migrate() -> set[str]:
|
||||
from reflex.components import ChakraComponent
|
||||
|
||||
rx_chakra_names = set(dir(reflex.chakra))
|
||||
|
||||
names_to_migrate = set()
|
||||
whitelist = {
|
||||
"CodeBlock",
|
||||
"ColorModeIcon",
|
||||
"MultiSelect",
|
||||
"MultiSelectOption",
|
||||
"base",
|
||||
"code_block",
|
||||
"color_mode_cond",
|
||||
"color_mode_icon",
|
||||
"multi_select",
|
||||
"multi_select_option",
|
||||
}
|
||||
for rx_chakra_name in sorted(rx_chakra_names):
|
||||
if rx_chakra_name.startswith("_"):
|
||||
continue
|
||||
|
||||
rx_chakra_object = getattr(reflex.chakra, rx_chakra_name)
|
||||
try:
|
||||
if (
|
||||
inspect.ismethod(rx_chakra_object)
|
||||
and inspect.isclass(rx_chakra_object.__self__)
|
||||
and issubclass(rx_chakra_object.__self__, ChakraComponent)
|
||||
):
|
||||
names_to_migrate.add(rx_chakra_name)
|
||||
|
||||
elif inspect.isclass(rx_chakra_object) and issubclass(
|
||||
rx_chakra_object, ChakraComponent
|
||||
):
|
||||
names_to_migrate.add(rx_chakra_name)
|
||||
pass
|
||||
else:
|
||||
# For the given rx.chakra.<x>, does rx.<x> exist?
|
||||
# And of these, should we include in migration?
|
||||
if hasattr(reflex, rx_chakra_name) and rx_chakra_name in whitelist:
|
||||
names_to_migrate.add(rx_chakra_name)
|
||||
|
||||
except Exception:
|
||||
raise
|
||||
return names_to_migrate
|
||||
|
||||
|
||||
def migrate_to_reflex():
|
||||
"""Migration from Pynecone to Reflex."""
|
||||
# Check if the old config file exists.
|
||||
|
13
scripts/migrate_project_to_rx_chakra.py
Normal file
13
scripts/migrate_project_to_rx_chakra.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""Migrate project to rx.chakra. I.e. switch usage of rx.<component> to rx.chakra.<component>."""
|
||||
|
||||
import argparse
|
||||
|
||||
if __name__ == "__main__":
|
||||
# parse args just for the help message (-h, etc)
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Migrate project to rx.chakra. I.e. switch usage of rx.<component> to rx.chakra.<component>."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
from reflex.utils.prerequisites import migrate_to_rx_chakra
|
||||
|
||||
migrate_to_rx_chakra()
|
Loading…
Reference in New Issue
Block a user