relationalai 0.11.4__py3-none-any.whl → 0.12.1__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.
- relationalai/clients/config.py +7 -0
- relationalai/clients/direct_access_client.py +113 -0
- relationalai/clients/snowflake.py +263 -189
- relationalai/clients/types.py +4 -1
- relationalai/clients/use_index_poller.py +72 -48
- relationalai/clients/util.py +9 -0
- relationalai/dsl.py +1 -2
- relationalai/early_access/metamodel/rewrite/__init__.py +5 -3
- relationalai/early_access/rel/rewrite/__init__.py +1 -1
- relationalai/environments/snowbook.py +10 -1
- relationalai/errors.py +24 -3
- relationalai/semantics/internal/annotations.py +1 -0
- relationalai/semantics/internal/internal.py +22 -3
- relationalai/semantics/lqp/builtins.py +1 -0
- relationalai/semantics/lqp/executor.py +12 -4
- relationalai/semantics/lqp/model2lqp.py +1 -0
- relationalai/semantics/lqp/passes.py +3 -4
- relationalai/semantics/{rel → lqp}/rewrite/__init__.py +6 -0
- relationalai/semantics/metamodel/builtins.py +12 -1
- relationalai/semantics/metamodel/executor.py +2 -1
- relationalai/semantics/metamodel/rewrite/__init__.py +3 -9
- relationalai/semantics/metamodel/rewrite/flatten.py +8 -7
- relationalai/semantics/reasoners/graph/core.py +1356 -258
- relationalai/semantics/rel/builtins.py +5 -1
- relationalai/semantics/rel/compiler.py +3 -3
- relationalai/semantics/rel/executor.py +20 -11
- relationalai/semantics/sql/compiler.py +2 -3
- relationalai/semantics/sql/executor/duck_db.py +8 -4
- relationalai/semantics/sql/executor/snowflake.py +1 -1
- relationalai/tools/cli.py +17 -6
- relationalai/tools/cli_controls.py +334 -352
- relationalai/tools/constants.py +1 -0
- relationalai/tools/query_utils.py +27 -0
- relationalai/util/otel_configuration.py +1 -1
- {relationalai-0.11.4.dist-info → relationalai-0.12.1.dist-info}/METADATA +5 -4
- {relationalai-0.11.4.dist-info → relationalai-0.12.1.dist-info}/RECORD +45 -45
- relationalai/semantics/metamodel/rewrite/gc_nodes.py +0 -58
- relationalai/semantics/metamodel/rewrite/list_types.py +0 -109
- /relationalai/semantics/{rel → lqp}/rewrite/cdc.py +0 -0
- /relationalai/semantics/{rel → lqp}/rewrite/extract_common.py +0 -0
- /relationalai/semantics/{metamodel → lqp}/rewrite/extract_keys.py +0 -0
- /relationalai/semantics/{metamodel → lqp}/rewrite/fd_constraints.py +0 -0
- /relationalai/semantics/{rel → lqp}/rewrite/quantify_vars.py +0 -0
- /relationalai/semantics/{metamodel → lqp}/rewrite/splinter.py +0 -0
- {relationalai-0.11.4.dist-info → relationalai-0.12.1.dist-info}/WHEEL +0 -0
- {relationalai-0.11.4.dist-info → relationalai-0.12.1.dist-info}/entry_points.txt +0 -0
- {relationalai-0.11.4.dist-info → relationalai-0.12.1.dist-info}/licenses/LICENSE +0 -0
relationalai/clients/config.py
CHANGED
|
@@ -468,6 +468,13 @@ class Config():
|
|
|
468
468
|
if not self.file_path:
|
|
469
469
|
self.file_path = "__inline__"
|
|
470
470
|
self._handle_snowflake_fallback_configurations()
|
|
471
|
+
# Check if Azure platform is being used without the legacy dependency
|
|
472
|
+
if self.get("platform", "") == "azure":
|
|
473
|
+
try:
|
|
474
|
+
import railib # noqa
|
|
475
|
+
except ImportError:
|
|
476
|
+
from relationalai.errors import AzureLegacyDependencyMissingException
|
|
477
|
+
raise AzureLegacyDependencyMissingException() from None
|
|
471
478
|
|
|
472
479
|
def fetch(self, profile:str|None=None):
|
|
473
480
|
from relationalai.environments import runtime_env, TerminalEnvironment
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from urllib.parse import urlencode, quote
|
|
6
|
+
from requests.adapters import HTTPAdapter
|
|
7
|
+
from urllib3.util.retry import Retry
|
|
8
|
+
from typing import Any, Dict, Optional, Tuple
|
|
9
|
+
|
|
10
|
+
from relationalai.auth.token_handler import TokenHandler
|
|
11
|
+
from relationalai.clients.config import Config
|
|
12
|
+
from relationalai.clients.util import get_pyrel_version
|
|
13
|
+
from relationalai import debugging
|
|
14
|
+
from relationalai.tools.constants import Generation
|
|
15
|
+
from relationalai.environments import runtime_env, SnowbookEnvironment
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Endpoint:
|
|
19
|
+
method: str
|
|
20
|
+
endpoint: str
|
|
21
|
+
|
|
22
|
+
class DirectAccessClient:
|
|
23
|
+
"""
|
|
24
|
+
DirectAccessClient is a client for direct service access without service function calls.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, config: Config, token_handler: TokenHandler, service_endpoint: str, generation: Optional[Generation] = None):
|
|
28
|
+
self._config: Config = config
|
|
29
|
+
self._token_handler: TokenHandler = token_handler
|
|
30
|
+
self.service_endpoint: str = service_endpoint
|
|
31
|
+
self.generation: Optional[Generation] = generation
|
|
32
|
+
self._is_snowflake_notebook = isinstance(runtime_env, SnowbookEnvironment)
|
|
33
|
+
self.endpoints: Dict[str, Endpoint] = {
|
|
34
|
+
"create_txn": Endpoint(method="POST", endpoint="/v1alpha1/transactions"),
|
|
35
|
+
"get_txn": Endpoint(method="GET", endpoint="/v1alpha1/transactions/{txn_id}"),
|
|
36
|
+
"get_txn_artifacts": Endpoint(method="GET", endpoint="/v1alpha1/transactions/{txn_id}/artifacts"),
|
|
37
|
+
"get_txn_problems": Endpoint(method="GET", endpoint="/v1alpha1/transactions/{txn_id}/problems"),
|
|
38
|
+
"get_txn_events": Endpoint(method="GET", endpoint="/v1alpha1/transactions/{txn_id}/events/{stream_name}"),
|
|
39
|
+
"get_package_versions": Endpoint(method="GET", endpoint="/v1alpha1/databases/{db_name}/package_versions"),
|
|
40
|
+
"get_model_package_versions": Endpoint(method="POST", endpoint="/v1alpha1/models/get_package_versions"),
|
|
41
|
+
"create_db": Endpoint(method="POST", endpoint="/v1alpha1/databases"),
|
|
42
|
+
"get_db": Endpoint(method="GET", endpoint="/v1alpha1/databases"),
|
|
43
|
+
"delete_db": Endpoint(method="DELETE", endpoint="/v1alpha1/databases/{db_name}"),
|
|
44
|
+
"release_index": Endpoint(method="POST", endpoint="/v1alpha1/index/release"),
|
|
45
|
+
"list_engines": Endpoint(method="GET", endpoint="/v1alpha1/engines"),
|
|
46
|
+
"get_engine": Endpoint(method="GET", endpoint="/v1alpha1/engines/{engine_type}/{engine_name}"),
|
|
47
|
+
"create_engine": Endpoint(method="POST", endpoint="/v1alpha1/engines/{engine_type}"),
|
|
48
|
+
"delete_engine": Endpoint(method="DELETE", endpoint="/v1alpha1/engines/{engine_type}/{engine_name}"),
|
|
49
|
+
"suspend_engine": Endpoint(method="POST", endpoint="/v1alpha1/engines/{engine_type}/{engine_name}/suspend"),
|
|
50
|
+
"resume_engine": Endpoint(method="POST", endpoint="/v1alpha1/engines/{engine_type}/{engine_name}/resume_async"),
|
|
51
|
+
"prepare_index": Endpoint(method="POST", endpoint="/v1alpha1/index/prepare"),
|
|
52
|
+
}
|
|
53
|
+
self.http_session = self._create_retry_session()
|
|
54
|
+
|
|
55
|
+
def _create_retry_session(self) -> requests.Session:
|
|
56
|
+
http_session = requests.Session()
|
|
57
|
+
retries = Retry(
|
|
58
|
+
total=3,
|
|
59
|
+
backoff_factor=0.3,
|
|
60
|
+
status_forcelist=[500, 502, 503, 504],
|
|
61
|
+
allowed_methods=frozenset({"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"}),
|
|
62
|
+
raise_on_status=False
|
|
63
|
+
)
|
|
64
|
+
adapter = HTTPAdapter(max_retries=retries)
|
|
65
|
+
http_session.mount("http://", adapter)
|
|
66
|
+
http_session.mount("https://", adapter)
|
|
67
|
+
http_session.headers.update({"Connection": "keep-alive"})
|
|
68
|
+
return http_session
|
|
69
|
+
|
|
70
|
+
def request(
|
|
71
|
+
self,
|
|
72
|
+
endpoint: str,
|
|
73
|
+
payload: Dict[str, Any] | None = None,
|
|
74
|
+
headers: Dict[str, str] | None = None,
|
|
75
|
+
path_params: Dict[str, str] | None = None,
|
|
76
|
+
query_params: Dict[str, str] | None = None,
|
|
77
|
+
) -> requests.Response:
|
|
78
|
+
"""
|
|
79
|
+
Send a request to the service endpoint.
|
|
80
|
+
"""
|
|
81
|
+
url, method = self._prepare_url(endpoint, path_params, query_params)
|
|
82
|
+
request_headers = self._prepare_headers(headers)
|
|
83
|
+
return self.http_session.request(method, url, json=payload, headers=request_headers)
|
|
84
|
+
|
|
85
|
+
def _prepare_url(self, endpoint: str, path_params: Dict[str, str] | None = None, query_params: Dict[str, str] | None = None) -> Tuple[str, str]:
|
|
86
|
+
try:
|
|
87
|
+
ep = self.endpoints[endpoint]
|
|
88
|
+
except KeyError:
|
|
89
|
+
raise ValueError(f"Invalid endpoint: {endpoint}. Available endpoints: {list(self.endpoints.keys())}")
|
|
90
|
+
url = f"{self.service_endpoint}{ep.endpoint}"
|
|
91
|
+
if path_params:
|
|
92
|
+
escaped_path_params = {k: quote(v, safe='') for k, v in path_params.items()}
|
|
93
|
+
url = url.format(**escaped_path_params)
|
|
94
|
+
if query_params:
|
|
95
|
+
url += '?' + urlencode(query_params)
|
|
96
|
+
return url, ep.method
|
|
97
|
+
|
|
98
|
+
def _prepare_headers(self, headers: Dict[str, str] | None) -> Dict[str, str]:
|
|
99
|
+
request_headers = {}
|
|
100
|
+
if headers:
|
|
101
|
+
request_headers.update(headers)
|
|
102
|
+
# Authorization tokens are not needed in a snowflake notebook environment
|
|
103
|
+
if not self._is_snowflake_notebook:
|
|
104
|
+
request_headers["Authorization"] = f'Snowflake Token="{self._token_handler.get_ingress_token(self.service_endpoint)}"'
|
|
105
|
+
# needed for oauth, does no harm for other authentication methods
|
|
106
|
+
request_headers["X-SF-SPCS-Authentication-Method"] = 'OAUTH'
|
|
107
|
+
request_headers["Content-Type"] = 'application/x-www-form-urlencoded'
|
|
108
|
+
request_headers["Accept"] = "application/json"
|
|
109
|
+
|
|
110
|
+
request_headers["user-agent"] = get_pyrel_version(self.generation)
|
|
111
|
+
request_headers["pyrel_program_id"] = debugging.get_program_span_id() or ""
|
|
112
|
+
|
|
113
|
+
return debugging.add_current_propagation_headers(request_headers)
|