|
5 | 5 | import concurrent.futures |
6 | 6 | import dataclasses |
7 | 7 | import enum |
| 8 | +import importlib |
8 | 9 | import inspect |
9 | 10 | import multiprocessing |
10 | 11 | import os |
|
24 | 25 | ) |
25 | 26 |
|
26 | 27 | from reflex import constants |
| 28 | +from reflex.plugins import Plugin |
27 | 29 | from reflex.utils.exceptions import EnvironmentVarValueError |
28 | 30 | from reflex.utils.types import GenericType, is_union, value_inside_optional |
29 | 31 |
|
@@ -126,6 +128,48 @@ def interpret_path_env(value: str, field_name: str) -> Path: |
126 | 128 | return Path(value) |
127 | 129 |
|
128 | 130 |
|
| 131 | +def interpret_plugin_env(value: str, field_name: str) -> Plugin: |
| 132 | + """Interpret a plugin environment variable value. |
| 133 | +
|
| 134 | + Args: |
| 135 | + value: The environment variable value. |
| 136 | + field_name: The field name. |
| 137 | +
|
| 138 | + Returns: |
| 139 | + The interpreted value. |
| 140 | +
|
| 141 | + Raises: |
| 142 | + EnvironmentVarValueError: If the value is invalid. |
| 143 | + """ |
| 144 | + if "." not in value: |
| 145 | + msg = f"Invalid plugin value: {value!r} for {field_name}. Plugin name must be in the format 'package.module.PluginName'." |
| 146 | + raise EnvironmentVarValueError(msg) |
| 147 | + |
| 148 | + import_path, plugin_name = value.rsplit(".", 1) |
| 149 | + |
| 150 | + try: |
| 151 | + module = importlib.import_module(import_path) |
| 152 | + except ImportError as e: |
| 153 | + msg = f"Failed to import module {import_path!r} for {field_name}: {e}" |
| 154 | + raise EnvironmentVarValueError(msg) from e |
| 155 | + |
| 156 | + try: |
| 157 | + plugin_class = getattr(module, plugin_name, None) |
| 158 | + except Exception as e: |
| 159 | + msg = f"Failed to get plugin class {plugin_name!r} from module {import_path!r} for {field_name}: {e}" |
| 160 | + raise EnvironmentVarValueError(msg) from e |
| 161 | + |
| 162 | + if not inspect.isclass(plugin_class) or not issubclass(plugin_class, Plugin): |
| 163 | + msg = f"Invalid plugin class: {plugin_name!r} for {field_name}. Must be a subclass of Plugin." |
| 164 | + raise EnvironmentVarValueError(msg) |
| 165 | + |
| 166 | + try: |
| 167 | + return plugin_class() |
| 168 | + except Exception as e: |
| 169 | + msg = f"Failed to instantiate plugin {plugin_name!r} for {field_name}: {e}" |
| 170 | + raise EnvironmentVarValueError(msg) from e |
| 171 | + |
| 172 | + |
129 | 173 | def interpret_enum_env(value: str, field_type: GenericType, field_name: str) -> Any: |
130 | 174 | """Interpret an enum environment variable value. |
131 | 175 |
|
@@ -181,6 +225,8 @@ def interpret_env_var_value( |
181 | 225 | return interpret_path_env(value, field_name) |
182 | 226 | if field_type is ExistingPath: |
183 | 227 | return interpret_existing_path_env(value, field_name) |
| 228 | + if field_type is Plugin: |
| 229 | + return interpret_plugin_env(value, field_name) |
184 | 230 | if get_origin(field_type) is list: |
185 | 231 | return [ |
186 | 232 | interpret_env_var_value( |
|
0 commit comments