fal 0.9.2__py3-none-any.whl → 0.9.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fal might be problematic. Click here for more details.

Files changed (93) hide show
  1. _fal_testing/utils.py +2 -2
  2. dbt/adapters/fal/__init__.py +21 -0
  3. dbt/adapters/fal/__version__.py +1 -0
  4. dbt/adapters/fal/connections.py +18 -0
  5. dbt/adapters/fal/impl.py +93 -0
  6. dbt/adapters/fal/load_db_profile.py +80 -0
  7. dbt/adapters/fal/wrappers.py +113 -0
  8. dbt/adapters/fal_experimental/__init__.py +11 -0
  9. dbt/adapters/fal_experimental/__version__.py +1 -0
  10. dbt/adapters/fal_experimental/adapter.py +149 -0
  11. dbt/adapters/fal_experimental/adapter_support.py +234 -0
  12. dbt/adapters/fal_experimental/connections.py +72 -0
  13. dbt/adapters/fal_experimental/impl.py +240 -0
  14. dbt/adapters/fal_experimental/support/athena.py +92 -0
  15. dbt/adapters/fal_experimental/support/bigquery.py +74 -0
  16. dbt/adapters/fal_experimental/support/duckdb.py +28 -0
  17. dbt/adapters/fal_experimental/support/postgres.py +88 -0
  18. dbt/adapters/fal_experimental/support/redshift.py +56 -0
  19. dbt/adapters/fal_experimental/support/snowflake.py +76 -0
  20. dbt/adapters/fal_experimental/support/trino.py +26 -0
  21. dbt/adapters/fal_experimental/telemetry/__init__.py +1 -0
  22. dbt/adapters/fal_experimental/telemetry/telemetry.py +411 -0
  23. dbt/adapters/fal_experimental/teleport.py +192 -0
  24. dbt/adapters/fal_experimental/teleport_adapter_support.py +23 -0
  25. dbt/adapters/fal_experimental/teleport_support/duckdb.py +122 -0
  26. dbt/adapters/fal_experimental/teleport_support/snowflake.py +72 -0
  27. dbt/adapters/fal_experimental/utils/__init__.py +50 -0
  28. dbt/adapters/fal_experimental/utils/environments.py +302 -0
  29. dbt/fal/adapters/python/__init__.py +3 -0
  30. dbt/fal/adapters/python/connections.py +319 -0
  31. dbt/fal/adapters/python/impl.py +291 -0
  32. dbt/fal/adapters/teleport/__init__.py +3 -0
  33. dbt/fal/adapters/teleport/impl.py +103 -0
  34. dbt/fal/adapters/teleport/info.py +73 -0
  35. dbt/include/fal/__init__.py +3 -0
  36. dbt/include/fal/dbt_project.yml +5 -0
  37. dbt/include/fal/macros/materializations/table.sql +46 -0
  38. dbt/include/fal/macros/teleport_duckdb.sql +8 -0
  39. dbt/include/fal/macros/teleport_snowflake.sql +31 -0
  40. dbt/include/fal_experimental/__init__.py +3 -0
  41. dbt/include/fal_experimental/dbt_project.yml +5 -0
  42. dbt/include/fal_experimental/macros/materializations/table.sql +36 -0
  43. fal/__init__.py +61 -11
  44. fal/dbt/__init__.py +11 -0
  45. fal/dbt/cli/__init__.py +1 -0
  46. fal/{cli → dbt/cli}/args.py +7 -2
  47. fal/{cli → dbt/cli}/cli.py +18 -3
  48. fal/{cli → dbt/cli}/dbt_runner.py +1 -1
  49. fal/{cli → dbt/cli}/fal_runner.py +6 -6
  50. fal/{cli → dbt/cli}/flow_runner.py +9 -9
  51. fal/{cli → dbt/cli}/model_generator/model_generator.py +5 -5
  52. fal/{cli → dbt/cli}/selectors.py +2 -2
  53. fal/{fal_script.py → dbt/fal_script.py} +4 -4
  54. {faldbt → fal/dbt/integration}/lib.py +2 -2
  55. {faldbt → fal/dbt/integration}/magics.py +2 -2
  56. {faldbt → fal/dbt/integration}/parse.py +7 -7
  57. {faldbt → fal/dbt/integration}/project.py +7 -7
  58. fal/dbt/integration/utils/yaml_helper.py +80 -0
  59. fal/dbt/new/project.py +43 -0
  60. fal/{node_graph.py → dbt/node_graph.py} +2 -2
  61. fal/{packages → dbt/packages}/dependency_analysis.py +32 -38
  62. fal/{packages → dbt/packages}/environments/__init__.py +3 -3
  63. fal/{packages → dbt/packages}/environments/base.py +2 -2
  64. fal/{packages → dbt/packages}/environments/conda.py +3 -3
  65. fal/{packages → dbt/packages}/environments/virtual_env.py +3 -3
  66. fal/{packages → dbt/packages}/isolated_runner.py +5 -5
  67. fal/{planner → dbt/planner}/executor.py +4 -4
  68. fal/{planner → dbt/planner}/plan.py +3 -3
  69. fal/{planner → dbt/planner}/schedule.py +5 -5
  70. fal/{planner → dbt/planner}/tasks.py +5 -5
  71. fal/{telemetry → dbt/telemetry}/telemetry.py +4 -4
  72. fal/{typing.py → dbt/typing.py} +2 -2
  73. fal/{utils.py → dbt/utils.py} +2 -2
  74. {fal-0.9.2.dist-info → fal-0.9.4.dist-info}/METADATA +98 -117
  75. fal-0.9.4.dist-info/RECORD +91 -0
  76. fal-0.9.4.dist-info/entry_points.txt +4 -0
  77. fal/cli/__init__.py +0 -1
  78. fal-0.9.2.dist-info/RECORD +0 -47
  79. fal-0.9.2.dist-info/entry_points.txt +0 -3
  80. {faldbt → dbt/adapters/fal_experimental}/utils/yaml_helper.py +0 -0
  81. /fal/{cli → dbt/cli}/model_generator/__init__.py +0 -0
  82. /fal/{cli → dbt/cli}/model_generator/module_check.py +0 -0
  83. /fal/{feature_store → dbt/feature_store}/__init__.py +0 -0
  84. /fal/{feature_store → dbt/feature_store}/feature.py +0 -0
  85. /fal/{packages → dbt/integration}/__init__.py +0 -0
  86. {faldbt → fal/dbt/integration}/logger.py +0 -0
  87. /fal/{planner → dbt/integration/utils}/__init__.py +0 -0
  88. {faldbt → fal/dbt/integration}/version.py +0 -0
  89. /fal/{telemetry → dbt/packages}/__init__.py +0 -0
  90. /fal/{packages → dbt/packages}/bridge.py +0 -0
  91. {faldbt → fal/dbt/planner}/__init__.py +0 -0
  92. {faldbt/utils → fal/dbt/telemetry}/__init__.py +0 -0
  93. {fal-0.9.2.dist-info → fal-0.9.4.dist-info}/WHEEL +0 -0
_fal_testing/utils.py CHANGED
@@ -43,8 +43,8 @@ def get_environment_type():
43
43
  # To determine whether this is a fal-created environment or not
44
44
  # we'll check whether the executable that is running this script
45
45
  # is located under any of the designated fal environment directories.
46
- from fal.packages.environments.virtual_env import _BASE_VENV_DIR
47
- from fal.packages.environments.conda import _BASE_CONDA_DIR
46
+ from fal.dbt.packages.environments.virtual_env import _BASE_VENV_DIR
47
+ from fal.dbt.packages.environments.conda import _BASE_CONDA_DIR
48
48
 
49
49
  executable_path = Path(sys.executable)
50
50
  for environment_type, prefix in [
@@ -0,0 +1,21 @@
1
+ from dbt.adapters.base import AdapterPlugin
2
+
3
+ from dbt.adapters.fal.connections import FalEncCredentials
4
+ from dbt.include import fal
5
+
6
+ # Avoid loading the plugin code for any import
7
+ def __getattr__(name):
8
+ if name == "FalEncAdapter":
9
+ from dbt.adapters.fal.impl import FalEncAdapter
10
+
11
+ return FalEncAdapter
12
+ if name == "Plugin":
13
+ from dbt.adapters.fal.impl import FalEncAdapter
14
+
15
+ return AdapterPlugin(
16
+ adapter=FalEncAdapter,
17
+ credentials=FalEncCredentials,
18
+ include_path=fal.PACKAGE_PATH
19
+ )
20
+
21
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1 @@
1
+ version = '0.9.4'
@@ -0,0 +1,18 @@
1
+ from dataclasses import dataclass
2
+ from dbt.adapters.fal_experimental.connections import FalCredentials
3
+
4
+
5
+ @dataclass
6
+ class FalEncCredentials(FalCredentials):
7
+ db_profile: str = ""
8
+
9
+ def _connection_keys(self):
10
+ return () + super()._connection_keys()
11
+
12
+ @property
13
+ def type(self):
14
+ return "fal"
15
+
16
+ @property
17
+ def unique_field(self):
18
+ return self.db_profile
@@ -0,0 +1,93 @@
1
+ from typing import Optional
2
+
3
+ from collections import defaultdict
4
+ from contextlib import contextmanager
5
+ from dbt.adapters.base.impl import BaseAdapter
6
+ from dbt.adapters.base.relation import BaseRelation
7
+ from dbt.adapters.protocol import AdapterConfig
8
+ from dbt.adapters.factory import FACTORY
9
+
10
+ # TODO: offer in `from isolate import is_agent`
11
+ from isolate.connections.common import is_agent
12
+
13
+ from .connections import FalEncCredentials
14
+ from .wrappers import FalEncAdapterWrapper, FalCredentialsWrapper
15
+
16
+ from .load_db_profile import load_profiles_info_1_5
17
+
18
+
19
+ class FalConfigs(AdapterConfig):
20
+ fal_environment: Optional[str]
21
+ fal_machine: Optional[str]
22
+
23
+
24
+ @contextmanager
25
+ def _release_plugin_lock():
26
+ FACTORY.lock.release()
27
+ try:
28
+ yield
29
+ finally:
30
+ FACTORY.lock.acquire()
31
+
32
+
33
+ DB_PROFILE = None
34
+ DB_RELATION = BaseRelation
35
+ OVERRIDE_PROPERTIES = {}
36
+
37
+ # NOTE: Should this file run on isolate agents? Could we skip it entirely and build a FalEncAdapterWrapper directly?
38
+ if not is_agent():
39
+ DB_PROFILE, OVERRIDE_PROPERTIES = load_profiles_info_1_5()
40
+ DB_RELATION = FACTORY.get_relation_class_by_name(DB_PROFILE.credentials.type)
41
+
42
+
43
+ class FalEncAdapter(BaseAdapter):
44
+ Relation = DB_RELATION # type: ignore
45
+
46
+ # TODO: how do we actually use this?
47
+ AdapterSpecificConfigs = FalConfigs
48
+
49
+ def __new__(cls, config):
50
+ # There are two different credentials types which can be passed to FalEncAdapter
51
+ # 1. FalEncCredentials
52
+ # 2. FalCredentialsWrapper
53
+ #
54
+ # For `FalEncCredentials`, we have to go through parsing the profiles.yml (so that we
55
+ # can obtain the real 'db' credentials). But for the other one, we can just use
56
+ # the bound credentials directly (e.g. in isolated mode where we don't actually
57
+ # have access to the profiles.yml file).
58
+
59
+ fal_credentials = config.credentials
60
+ if isinstance(fal_credentials, FalEncCredentials):
61
+ db_credentials = DB_PROFILE.credentials
62
+ else:
63
+ # Since profile construction (in the case above) already registers the
64
+ # adapter plugin for the db type, we need to also mimic that here.
65
+ assert isinstance(fal_credentials, FalCredentialsWrapper)
66
+ db_credentials = fal_credentials._db_creds
67
+ with _release_plugin_lock():
68
+ FACTORY.load_plugin(db_credentials.type)
69
+
70
+ # TODO: maybe we can do this better?
71
+ with _release_plugin_lock():
72
+ db_adapter_class = FACTORY.get_adapter_class_by_name(db_credentials.type)
73
+ original_plugin = FACTORY.get_plugin_by_name(fal_credentials.type)
74
+ original_plugin.dependencies = [db_credentials.type]
75
+
76
+ config.python_adapter_credentials = fal_credentials
77
+ config.sql_adapter_credentials = db_credentials
78
+
79
+ for key in OVERRIDE_PROPERTIES:
80
+ if OVERRIDE_PROPERTIES[key] is not None:
81
+ setattr(config, key, OVERRIDE_PROPERTIES[key])
82
+
83
+ with _release_plugin_lock():
84
+ # Temporary credentials for register
85
+ config.credentials = config.sql_adapter_credentials
86
+ FACTORY.register_adapter(config)
87
+ config.credentials = FalCredentialsWrapper(config.sql_adapter_credentials)
88
+
89
+ return FalEncAdapterWrapper(db_adapter_class, config)
90
+
91
+ @classmethod
92
+ def type(cls):
93
+ return "fal"
@@ -0,0 +1,80 @@
1
+ from typing import Dict, Any, Tuple, Optional
2
+
3
+ from dbt.flags import get_flags, Namespace
4
+ from dbt.config.project import load_raw_project
5
+ from dbt.config.profile import read_profile, Profile
6
+ from dbt.config.renderer import ProfileRenderer
7
+
8
+
9
+ # NOTE: inspired in https://github.com/dbt-labs/dbt-core/blob/828d723512fced809c63e369a82c7eb570a74986/core/dbt/config/runtime.py#L58-L74
10
+ def find_profile_name(
11
+ profile_override: Optional[str],
12
+ project_root: str,
13
+ profile_renderer: ProfileRenderer,
14
+ ):
15
+ if profile_override is not None:
16
+ profile_name = profile_override
17
+ else:
18
+ raw_project = load_raw_project(project_root)
19
+ raw_profile_name = raw_project.get("profile")
20
+ profile_name = profile_renderer.render_value(raw_profile_name)
21
+
22
+ return profile_name
23
+
24
+
25
+ # NOTE: inspired in https://github.com/dbt-labs/dbt-core/blob/828d723512fced809c63e369a82c7eb570a74986/core/dbt/config/profile.py#L279-L311
26
+ def find_target_name(
27
+ target_override: Optional[str], raw_profile: dict, profile_renderer: ProfileRenderer
28
+ ):
29
+ if target_override is not None:
30
+ target_name = target_override
31
+ elif "target" in raw_profile:
32
+ # render the target if it was parsed from yaml
33
+ target_name = profile_renderer.render_value(raw_profile["target"])
34
+ else:
35
+ target_name = "default"
36
+
37
+ return target_name
38
+
39
+
40
+ def load_profiles_info_1_5() -> Tuple[Profile, Dict[str, Any]]:
41
+ flags: Namespace = get_flags()
42
+
43
+ profile_renderer = ProfileRenderer(getattr(flags, "VARS", {}))
44
+
45
+ profile_name = find_profile_name(flags.PROFILE, flags.PROJECT_DIR, profile_renderer)
46
+
47
+ raw_profiles = read_profile(flags.PROFILES_DIR)
48
+ raw_profile = raw_profiles[profile_name]
49
+
50
+ target_name = find_target_name(flags.TARGET, raw_profile, profile_renderer)
51
+
52
+ fal_dict = Profile._get_profile_data(
53
+ profile=raw_profile,
54
+ profile_name=profile_name,
55
+ target_name=target_name,
56
+ )
57
+ db_profile_target_name = fal_dict.get("db_profile")
58
+ assert (
59
+ db_profile_target_name
60
+ ), "fal credentials must have a `db_profile` property set"
61
+
62
+ try:
63
+ db_profile = Profile.from_raw_profile_info(
64
+ raw_profile=raw_profile,
65
+ profile_name=profile_name,
66
+ renderer=profile_renderer,
67
+ # TODO: should we load the user_config?
68
+ user_config={},
69
+ target_override=db_profile_target_name,
70
+ )
71
+ except RecursionError as error:
72
+ raise AttributeError(
73
+ "Did you wrap a type 'fal' profile with another type 'fal' profile?"
74
+ ) from error
75
+
76
+ override_properties = {
77
+ "threads": getattr(flags, "THREADS", None) or fal_dict.get("threads") or db_profile.threads,
78
+ }
79
+
80
+ return db_profile, override_properties
@@ -0,0 +1,113 @@
1
+ from typing import Any, Optional, Type, Set
2
+
3
+ from dbt.adapters.factory import get_adapter_by_type
4
+ from dbt.adapters.base.meta import available
5
+ from dbt.adapters.base.impl import BaseAdapter
6
+ from dbt.contracts.connection import Credentials
7
+ from dbt.parser.manifest import ManifestLoader
8
+ from dbt.clients.jinja import MacroGenerator
9
+
10
+ from ..fal_experimental.utils import cache_static
11
+ from ..fal_experimental.impl import FalAdapterMixin
12
+ from ..fal_experimental import telemetry
13
+
14
+
15
+ class FalCredentialsWrapper:
16
+ _db_creds: Optional[Credentials] = None
17
+
18
+ def __init__(self, db_creds: Credentials):
19
+ self._db_creds = db_creds
20
+
21
+ @property
22
+ def type(self):
23
+ if find_funcs_in_stack({"to_target_dict", "db_materialization"}):
24
+ # This makes sense for both SQL and Python because the target is always the db
25
+ return self._db_creds.type
26
+
27
+ return "fal"
28
+
29
+ def __getattr__(self, name: str) -> Any:
30
+ """
31
+ Directly proxy to the DB adapter, just shadowing the type
32
+ """
33
+ return getattr(self._db_creds, name)
34
+
35
+
36
+ class FalEncAdapterWrapper(FalAdapterMixin):
37
+ def __init__(self, db_adapter_type: Type[BaseAdapter], config):
38
+ # Use the db_adapter_type connection manager
39
+ self.ConnectionManager = db_adapter_type.ConnectionManager
40
+
41
+ db_adapter = get_adapter_by_type(db_adapter_type.type())
42
+ super().__init__(config, db_adapter)
43
+
44
+ # HACK: A Python adapter does not have self._available_ all the attributes a DB adapter does.
45
+ # Since we use the DB adapter as the storage for the Python adapter, we must proxy to it
46
+ # all the unhandled calls.
47
+
48
+ # self._available_ is set by metaclass=AdapterMeta
49
+ self._available_ = self._db_adapter._available_.union(self._available_)
50
+ # self._parse_replacements_ is set by metaclass=AdapterMeta
51
+ self._parse_replacements_.update(self._db_adapter._parse_replacements_)
52
+
53
+ telemetry.log_api(
54
+ "encapsulate_init",
55
+ config=config,
56
+ additional_props={
57
+ "is_teleport": self.is_teleport(),
58
+ "fal_host": self.credentials.host,
59
+ },
60
+ )
61
+
62
+ def submit_python_job(self, *args, **kwargs):
63
+ return super().submit_python_job(*args, **kwargs)
64
+
65
+ @available
66
+ @telemetry.log_call(
67
+ "encapsulate_db_materialization", log_args=["materialization"], config=True
68
+ )
69
+ def db_materialization(self, context: dict, materialization: str):
70
+ # NOTE: inspired by https://github.com/dbt-labs/dbt-core/blob/be4a91a0fe35a619587b7a0145e190690e3771c6/core/dbt/task/run.py#L254-L290
71
+ materialization_macro = self.manifest.find_materialization_macro_by_name(
72
+ self.config.project_name, materialization, self._db_adapter.type()
73
+ )
74
+
75
+ # HACK: run the entire SQL materialization and return the resulting dict with relations created
76
+ return MacroGenerator(
77
+ materialization_macro, context, stack=context["context_macro_stack"]
78
+ )()
79
+
80
+ @property
81
+ @cache_static
82
+ def manifest(self):
83
+ return ManifestLoader.get_full_manifest(self.config)
84
+
85
+ def type(self):
86
+ # NOTE: This does not let `fal__` macros to be used
87
+ # Maybe for 1.5 we will get a more reliable way to detect if we are in a SQL or Python context
88
+ if find_funcs_in_stack({"render", "db_materialization"}):
89
+ return self._db_adapter.type()
90
+
91
+ return "fal"
92
+
93
+ def __getattr__(self, name):
94
+ """
95
+ Directly proxy to the DB adapter, Python adapter in this case does what we explicitly define in this class.
96
+ """
97
+ if hasattr(self._db_adapter, name):
98
+ return getattr(self._db_adapter, name)
99
+ else:
100
+ getattr(super(), name)
101
+
102
+
103
+ def find_funcs_in_stack(funcs: Set[str]) -> bool:
104
+ import inspect
105
+
106
+ # NOTE: from https://stackoverflow.com/a/42636264/1276441
107
+ frame = inspect.currentframe()
108
+ while frame:
109
+ if frame.f_code.co_name in funcs:
110
+ return True
111
+ frame = frame.f_back
112
+
113
+ return False
@@ -0,0 +1,11 @@
1
+ from dbt.adapters.base import AdapterPlugin
2
+
3
+ from dbt.adapters.fal_experimental.connections import FalCredentials
4
+ from dbt.adapters.fal_experimental.impl import FalAdapter
5
+ from dbt.include import fal_experimental
6
+
7
+ Plugin = AdapterPlugin(
8
+ adapter=FalAdapter,
9
+ credentials=FalCredentials,
10
+ include_path=fal_experimental.PACKAGE_PATH,
11
+ )
@@ -0,0 +1 @@
1
+ version = '0.9.4'
@@ -0,0 +1,149 @@
1
+ from __future__ import annotations
2
+
3
+ import zipfile
4
+ import io
5
+ from functools import partial
6
+ from tempfile import NamedTemporaryFile
7
+ from typing import Any, Optional
8
+
9
+ from dbt.adapters.base.impl import BaseAdapter
10
+ from dbt.config.runtime import RuntimeConfig
11
+ from dbt.contracts.connection import AdapterResponse
12
+ from dbt.flags import get_flags, Namespace
13
+
14
+ from fal_serverless import FalServerlessHost, isolated
15
+ from dbt.adapters.fal_experimental.utils.environments import (
16
+ EnvironmentDefinition,
17
+ get_default_pip_dependencies
18
+ )
19
+
20
+ from dbt.parser.manifest import MacroManifest, Manifest
21
+
22
+ from .adapter_support import (
23
+ prepare_for_adapter,
24
+ read_relation_as_df,
25
+ reconstruct_adapter,
26
+ write_df_to_relation,
27
+ )
28
+
29
+ from .utils import extra_path, get_fal_scripts_path, retrieve_symbol
30
+
31
+
32
+ def run_with_adapter(code: str, adapter: BaseAdapter, config: RuntimeConfig) -> Any:
33
+ # main symbol is defined during dbt-fal's compilation
34
+ # and acts as an entrypoint for us to run the model.
35
+ fal_scripts_path = str(get_fal_scripts_path(config))
36
+ with extra_path(fal_scripts_path):
37
+ main = retrieve_symbol(code, "main")
38
+ return main(
39
+ read_df=prepare_for_adapter(adapter, read_relation_as_df),
40
+ write_df=prepare_for_adapter(adapter, write_df_to_relation),
41
+ )
42
+
43
+
44
+ def _isolated_runner(
45
+ code: str,
46
+ flags: Namespace,
47
+ config: RuntimeConfig,
48
+ manifest: Manifest,
49
+ macro_manifest: MacroManifest,
50
+ local_packages: Optional[bytes] = None,
51
+ ) -> Any:
52
+ # This function can be run in an entirely separate
53
+ # process or an environment, so we need to reconstruct
54
+ # the DB adapter solely from the config.
55
+ adapter = reconstruct_adapter(flags, config, manifest, macro_manifest)
56
+ fal_scripts_path = get_fal_scripts_path(config)
57
+ if local_packages is not None:
58
+ if fal_scripts_path.exists():
59
+ import shutil
60
+ shutil.rmtree(fal_scripts_path)
61
+ fal_scripts_path.parent.mkdir(parents=True, exist_ok=True)
62
+ zip_file = zipfile.ZipFile(io.BytesIO(local_packages))
63
+ zip_file.extractall(fal_scripts_path)
64
+
65
+ return run_with_adapter(code, adapter, config)
66
+
67
+
68
+ def run_in_environment_with_adapter(
69
+ environment: EnvironmentDefinition,
70
+ code: str,
71
+ config: RuntimeConfig,
72
+ manifest: Manifest,
73
+ macro_manifest: MacroManifest,
74
+ adapter_type: str
75
+ ) -> AdapterResponse:
76
+ """Run the 'main' function inside the given code on the
77
+ specified environment.
78
+
79
+ The environment_name must be defined inside fal_project.yml file
80
+ in your project's root directory."""
81
+ compressed_local_packages = None
82
+
83
+ is_remote = type(environment.host) is FalServerlessHost
84
+
85
+ deps = get_default_pip_dependencies(
86
+ is_remote=is_remote,
87
+ adapter_type=adapter_type)
88
+
89
+ fal_scripts_path = get_fal_scripts_path(config)
90
+
91
+ if is_remote and fal_scripts_path.exists():
92
+ with NamedTemporaryFile() as temp_file:
93
+ with zipfile.ZipFile(
94
+ temp_file.name, "w", zipfile.ZIP_DEFLATED
95
+ ) as zip_file:
96
+ for entry in fal_scripts_path.rglob("*"):
97
+ zip_file.write(entry, entry.relative_to(fal_scripts_path))
98
+
99
+ compressed_local_packages = temp_file.read()
100
+
101
+ execute_model = partial(
102
+ _isolated_runner,
103
+ code=code,
104
+ flags=get_flags(),
105
+ config=config,
106
+ manifest=manifest,
107
+ macro_manifest=macro_manifest,
108
+ local_packages=compressed_local_packages
109
+ )
110
+
111
+ if environment.kind == "local":
112
+ result = execute_model()
113
+ return result
114
+
115
+ extra = {}
116
+ if is_remote:
117
+ # Machine type is only applicable in FalServerlesshost
118
+ extra = {"machine_type": environment.machine_type}
119
+
120
+ if environment.kind == "virtualenv":
121
+ requirements = environment.config.get("requirements", [])
122
+ requirements += deps
123
+ isolated_function = isolated(
124
+ kind="virtualenv",
125
+ host=environment.host,
126
+ requirements=requirements,
127
+ **extra
128
+ )(execute_model)
129
+ elif environment.kind == "conda":
130
+ dependencies = environment.config.pop("packages", [])
131
+ dependencies.append({"pip": deps})
132
+ env_dict = {
133
+ "name": "dbt_fal_env",
134
+ "channels": ["conda-forge", "defaults"],
135
+ "dependencies": dependencies
136
+ }
137
+ isolated_function = isolated(
138
+ kind="conda",
139
+ host=environment.host,
140
+ env_dict=env_dict,
141
+ **extra
142
+ )(execute_model)
143
+ else:
144
+ # We should not reach this point, because environment types are validated when the
145
+ # environment objects are created (in utils/environments.py).
146
+ raise Exception(f"Environment type not supported: {environment.kind}")
147
+
148
+ result = isolated_function()
149
+ return result