Resolve --envfile + --env into a single dict of env vars. Mirrors the precedence of the existing `reflex deploy` / `reflex secrets update` flow: when both are provided, --envfile wins and --env is discarded with a warning. Empty values are preserved as empty strings; keys defined wi
(envfile: str | None, envs: tuple[str, ...])
| 675 | |
| 676 | |
| 677 | def _parse_envs(envfile: str | None, envs: tuple[str, ...]) -> dict[str, str]: |
| 678 | """Resolve --envfile + --env into a single dict of env vars. |
| 679 | |
| 680 | Mirrors the precedence of the existing `reflex deploy` / `reflex secrets |
| 681 | update` flow: when both are provided, --envfile wins and --env is |
| 682 | discarded with a warning. Empty values are preserved as empty strings; |
| 683 | keys defined without a value in the envfile (``FOO`` with no ``=``) |
| 684 | become empty strings rather than ``None``. |
| 685 | |
| 686 | Args: |
| 687 | envfile: Path to a .env file, or None. |
| 688 | envs: Tuple of ``KEY=VALUE`` strings from repeated --env flags. |
| 689 | |
| 690 | Returns: |
| 691 | Dict of env var name → string value. Empty when neither input is set. |
| 692 | |
| 693 | """ |
| 694 | from reflex_cli.utils import hosting |
| 695 | |
| 696 | if envfile and envs: |
| 697 | console.warn("--envfile is set; ignoring --env") |
| 698 | |
| 699 | if envfile: |
| 700 | try: |
| 701 | from dotenv import dotenv_values # pyright: ignore[reportMissingImports] |
| 702 | except ImportError: |
| 703 | console.error( |
| 704 | 'The `python-dotenv` package is required for --envfile. Run `pip install "python-dotenv>=1.0.1"`.' |
| 705 | ) |
| 706 | raise click.exceptions.Exit(1) from None |
| 707 | return { |
| 708 | k: (v if v is not None else "") for k, v in dotenv_values(envfile).items() |
| 709 | } |
| 710 | |
| 711 | if envs: |
| 712 | return hosting.process_envs(list(envs)) |
| 713 | |
| 714 | return {} |
| 715 | |
| 716 | |
| 717 | def _format_env_vars_yaml(envs: dict[str, str]) -> str: |