relationalai 0.13.1__py3-none-any.whl → 0.13.2__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/client.py +49 -14
- relationalai/clients/local.py +23 -8
- relationalai/clients/resources/azure/azure.py +36 -11
- relationalai/clients/resources/snowflake/__init__.py +3 -3
- relationalai/clients/resources/snowflake/cli_resources.py +12 -1
- relationalai/clients/resources/snowflake/direct_access_resources.py +57 -17
- relationalai/clients/resources/snowflake/engine_service.py +381 -0
- relationalai/clients/resources/snowflake/engine_state_handlers.py +35 -29
- relationalai/clients/resources/snowflake/error_handlers.py +43 -2
- relationalai/clients/resources/snowflake/snowflake.py +116 -121
- relationalai/clients/types.py +5 -0
- relationalai/errors.py +1 -1
- relationalai/semantics/metamodel/typer/typer.py +6 -2
- relationalai/tools/cli.py +339 -186
- relationalai/tools/cli_helpers.py +410 -6
- {relationalai-0.13.1.dist-info → relationalai-0.13.2.dist-info}/METADATA +1 -1
- {relationalai-0.13.1.dist-info → relationalai-0.13.2.dist-info}/RECORD +21 -20
- relationalai_test_util/fixtures.py +2 -2
- {relationalai-0.13.1.dist-info → relationalai-0.13.2.dist-info}/WHEEL +0 -0
- {relationalai-0.13.1.dist-info → relationalai-0.13.2.dist-info}/entry_points.txt +0 -0
- {relationalai-0.13.1.dist-info → relationalai-0.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -39,6 +39,7 @@ from ...types import AvailableModel, EngineState, Import, ImportSource, ImportSo
|
|
|
39
39
|
from ...config import Config
|
|
40
40
|
from ...client import Client, ExportParams, ProviderBase, ResourcesBase
|
|
41
41
|
from ...util import IdentityParser, escape_for_f_string, get_pyrel_version, get_with_retries, poll_with_specified_overhead, safe_json_loads, sanitize_module_name, scrub_exception, wrap_with_request_id, normalize_datetime
|
|
42
|
+
from .engine_service import EngineServiceSQL, EngineType
|
|
42
43
|
from .util import (
|
|
43
44
|
collect_error_messages,
|
|
44
45
|
process_jinja_template,
|
|
@@ -64,6 +65,7 @@ from .error_handlers import (
|
|
|
64
65
|
ErrorHandler,
|
|
65
66
|
DuoSecurityErrorHandler,
|
|
66
67
|
AppMissingErrorHandler,
|
|
68
|
+
AppFunctionMissingErrorHandler,
|
|
67
69
|
DatabaseErrorsHandler,
|
|
68
70
|
EngineErrorsHandler,
|
|
69
71
|
ServiceNotStartedErrorHandler,
|
|
@@ -90,16 +92,10 @@ from .engine_state_handlers import (
|
|
|
90
92
|
# Constants
|
|
91
93
|
#--------------------------------------------------
|
|
92
94
|
|
|
93
|
-
VALID_POOL_STATUS = ["ACTIVE", "IDLE", "SUSPENDED"]
|
|
94
95
|
# transaction list and get return different fields (duration vs timings)
|
|
95
96
|
LIST_TXN_SQL_FIELDS = ["id", "database_name", "engine_name", "state", "abort_reason", "read_only","created_by", "created_on", "finished_at", "duration"]
|
|
96
97
|
GET_TXN_SQL_FIELDS = ["id", "database", "engine", "state", "abort_reason", "read_only","created_by", "created_on", "finished_at", "timings"]
|
|
97
98
|
VALID_ENGINE_STATES = ["READY", "PENDING"]
|
|
98
|
-
|
|
99
|
-
# Cloud-specific engine sizes
|
|
100
|
-
INTERNAL_ENGINE_SIZES = ["XS", "S", "M", "L"]
|
|
101
|
-
ENGINE_SIZES_AWS = ["HIGHMEM_X64_S", "HIGHMEM_X64_M", "HIGHMEM_X64_L"]
|
|
102
|
-
ENGINE_SIZES_AZURE = ["HIGHMEM_X64_S", "HIGHMEM_X64_M", "HIGHMEM_X64_SL"]
|
|
103
99
|
# Note: ENGINE_ERRORS, ENGINE_NOT_READY_MSGS, DATABASE_ERRORS moved to util.py
|
|
104
100
|
PYREL_ROOT_DB = 'pyrel_root_db'
|
|
105
101
|
|
|
@@ -184,11 +180,17 @@ class Resources(ResourcesBase):
|
|
|
184
180
|
self._sproc_models = None
|
|
185
181
|
# Store language for backward compatibility (used by child classes for use_index polling)
|
|
186
182
|
self.language = language
|
|
183
|
+
# Engine subsystem (composition: keeps engine CRUD isolated from the core Resources class)
|
|
184
|
+
self._engines = EngineServiceSQL(self)
|
|
187
185
|
# Register error and state handlers
|
|
188
186
|
self._register_handlers()
|
|
189
187
|
# Register atexit callback to cancel pending transactions
|
|
190
188
|
atexit.register(self.cancel_pending_transactions)
|
|
191
189
|
|
|
190
|
+
@property
|
|
191
|
+
def engines(self) -> EngineServiceSQL:
|
|
192
|
+
return self._engines
|
|
193
|
+
|
|
192
194
|
#--------------------------------------------------
|
|
193
195
|
# Initialization & Properties
|
|
194
196
|
#--------------------------------------------------
|
|
@@ -217,11 +219,12 @@ class Resources(ResourcesBase):
|
|
|
217
219
|
return handlers
|
|
218
220
|
"""
|
|
219
221
|
return [
|
|
220
|
-
DuoSecurityErrorHandler(),
|
|
221
222
|
AppMissingErrorHandler(),
|
|
223
|
+
AppFunctionMissingErrorHandler(),
|
|
224
|
+
ServiceNotStartedErrorHandler(),
|
|
225
|
+
DuoSecurityErrorHandler(),
|
|
222
226
|
DatabaseErrorsHandler(),
|
|
223
227
|
EngineErrorsHandler(),
|
|
224
|
-
ServiceNotStartedErrorHandler(),
|
|
225
228
|
TransactionAbortedErrorHandler(),
|
|
226
229
|
]
|
|
227
230
|
|
|
@@ -613,7 +616,7 @@ class Resources(ResourcesBase):
|
|
|
613
616
|
|
|
614
617
|
# Validate engine size
|
|
615
618
|
if engine_size:
|
|
616
|
-
is_size_valid, sizes = self.validate_engine_size(engine_size)
|
|
619
|
+
is_size_valid, sizes = self._engines.validate_engine_size(engine_size)
|
|
617
620
|
if not is_size_valid:
|
|
618
621
|
error_msg = f"Invalid engine size '{engine_size}'. Valid sizes are: {', '.join(sizes)}"
|
|
619
622
|
if use_default_size:
|
|
@@ -703,67 +706,27 @@ class Resources(ResourcesBase):
|
|
|
703
706
|
if not handled:
|
|
704
707
|
raise EngineProvisioningFailed(engine_name, error) from error
|
|
705
708
|
|
|
706
|
-
def validate_engine_size(self, size: str) -> Tuple[bool, List[str]]:
|
|
707
|
-
if size is not None:
|
|
708
|
-
sizes = self.get_engine_sizes()
|
|
709
|
-
if size not in sizes:
|
|
710
|
-
return False, sizes
|
|
711
|
-
return True, []
|
|
712
|
-
|
|
713
709
|
def get_engine_sizes(self, cloud_provider: str|None=None):
|
|
714
|
-
|
|
715
|
-
if cloud_provider is None:
|
|
716
|
-
cloud_provider = self.get_cloud_provider()
|
|
717
|
-
if cloud_provider == 'azure':
|
|
718
|
-
sizes = ENGINE_SIZES_AZURE
|
|
719
|
-
else:
|
|
720
|
-
sizes = ENGINE_SIZES_AWS
|
|
721
|
-
if self.config.show_all_engine_sizes():
|
|
722
|
-
return INTERNAL_ENGINE_SIZES + sizes
|
|
723
|
-
else:
|
|
724
|
-
return sizes
|
|
710
|
+
return self._engines.get_engine_sizes(cloud_provider=cloud_provider)
|
|
725
711
|
|
|
726
|
-
def list_engines(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
"updated_on": row["UPDATED_ON"],
|
|
741
|
-
}
|
|
742
|
-
for row in results
|
|
743
|
-
]
|
|
744
|
-
|
|
745
|
-
def get_engine(self, name: str):
|
|
746
|
-
results = self._exec(
|
|
747
|
-
f"SELECT NAME, ID, SIZE, STATUS, CREATED_BY, CREATED_ON, UPDATED_ON, VERSION, AUTO_SUSPEND_MINS, SUSPENDS_AT FROM {APP_NAME}.api.engines WHERE NAME='{name}';"
|
|
712
|
+
def list_engines(
|
|
713
|
+
self,
|
|
714
|
+
state: str | None = None,
|
|
715
|
+
name: str | None = None,
|
|
716
|
+
type: str | None = None,
|
|
717
|
+
size: str | None = None,
|
|
718
|
+
created_by: str | None = None,
|
|
719
|
+
):
|
|
720
|
+
return self._engines.list_engines(
|
|
721
|
+
state=state,
|
|
722
|
+
name=name,
|
|
723
|
+
type=type,
|
|
724
|
+
size=size,
|
|
725
|
+
created_by=created_by,
|
|
748
726
|
)
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
if not engine:
|
|
753
|
-
return None
|
|
754
|
-
engine_state: EngineState = {
|
|
755
|
-
"name": engine["NAME"],
|
|
756
|
-
"id": engine["ID"],
|
|
757
|
-
"size": engine["SIZE"],
|
|
758
|
-
"state": engine["STATUS"], # callers are expecting 'state'
|
|
759
|
-
"created_by": engine["CREATED_BY"],
|
|
760
|
-
"created_on": engine["CREATED_ON"],
|
|
761
|
-
"updated_on": engine["UPDATED_ON"],
|
|
762
|
-
"version": engine["VERSION"],
|
|
763
|
-
"auto_suspend": engine["AUTO_SUSPEND_MINS"],
|
|
764
|
-
"suspends_at": engine["SUSPENDS_AT"]
|
|
765
|
-
}
|
|
766
|
-
return engine_state
|
|
727
|
+
|
|
728
|
+
def get_engine(self, name: str, type: str):
|
|
729
|
+
return self._engines.get_engine(name, type)
|
|
767
730
|
|
|
768
731
|
def get_default_engine_name(self) -> str:
|
|
769
732
|
if self.config.get("engine_name", None) is not None:
|
|
@@ -784,60 +747,82 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
784
747
|
def is_valid_engine_state(self, name:str):
|
|
785
748
|
return name in VALID_ENGINE_STATES
|
|
786
749
|
|
|
750
|
+
# Can be overridden by subclasses (e.g. DirectAccessResources)
|
|
787
751
|
def _create_engine(
|
|
788
752
|
self,
|
|
789
753
|
name: str,
|
|
754
|
+
type: str = EngineType.LOGIC,
|
|
790
755
|
size: str | None = None,
|
|
791
756
|
auto_suspend_mins: int | None= None,
|
|
792
757
|
is_async: bool = False,
|
|
793
758
|
headers: Dict | None = None,
|
|
759
|
+
settings: Dict[str, Any] | None = None,
|
|
794
760
|
):
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
# check in case the config default is missing
|
|
805
|
-
if auto_suspend_mins is None:
|
|
806
|
-
self._exec(f"call {APP_NAME}.api.{api}('{name}', '{size}', null, {headers});")
|
|
807
|
-
else:
|
|
808
|
-
self._exec(f"call {APP_NAME}.api.{api}('{name}', '{size}', PARSE_JSON('{{\"auto_suspend_mins\": {auto_suspend_mins}}}'), {headers});")
|
|
809
|
-
except Exception as e:
|
|
810
|
-
raise EngineProvisioningFailed(name, e) from e
|
|
761
|
+
return self._engines._create_engine(
|
|
762
|
+
name=name,
|
|
763
|
+
type=type,
|
|
764
|
+
size=size,
|
|
765
|
+
auto_suspend_mins=auto_suspend_mins,
|
|
766
|
+
is_async=is_async,
|
|
767
|
+
headers=headers,
|
|
768
|
+
settings=settings,
|
|
769
|
+
)
|
|
811
770
|
|
|
812
|
-
def create_engine(
|
|
813
|
-
self
|
|
771
|
+
def create_engine(
|
|
772
|
+
self,
|
|
773
|
+
name: str,
|
|
774
|
+
type: str | None = None,
|
|
775
|
+
size: str | None = None,
|
|
776
|
+
auto_suspend_mins: int | None = None,
|
|
777
|
+
headers: Dict | None = None,
|
|
778
|
+
settings: Dict[str, Any] | None = None,
|
|
779
|
+
):
|
|
780
|
+
if type is None:
|
|
781
|
+
type = EngineType.LOGIC
|
|
782
|
+
# Route through _create_engine so subclasses (e.g. DirectAccessResources)
|
|
783
|
+
# can override engine creation behavior.
|
|
784
|
+
return self._create_engine(
|
|
785
|
+
name=name,
|
|
786
|
+
type=type,
|
|
787
|
+
size=size,
|
|
788
|
+
auto_suspend_mins=auto_suspend_mins,
|
|
789
|
+
is_async=False,
|
|
790
|
+
headers=headers,
|
|
791
|
+
settings=settings,
|
|
792
|
+
)
|
|
814
793
|
|
|
815
|
-
def create_engine_async(
|
|
816
|
-
self
|
|
794
|
+
def create_engine_async(
|
|
795
|
+
self,
|
|
796
|
+
name: str,
|
|
797
|
+
type: str = EngineType.LOGIC,
|
|
798
|
+
size: str | None = None,
|
|
799
|
+
auto_suspend_mins: int | None = None,
|
|
800
|
+
):
|
|
801
|
+
# Route through _create_engine so subclasses (e.g. DirectAccessResources)
|
|
802
|
+
# can override async engine creation behavior.
|
|
803
|
+
return self._create_engine(
|
|
804
|
+
name=name,
|
|
805
|
+
type=type,
|
|
806
|
+
size=size,
|
|
807
|
+
auto_suspend_mins=auto_suspend_mins,
|
|
808
|
+
is_async=True,
|
|
809
|
+
)
|
|
817
810
|
|
|
818
|
-
def delete_engine(self, name:str,
|
|
819
|
-
|
|
820
|
-
self._exec(f"call {APP_NAME}.api.delete_engine('{name}', {force},{request_headers});")
|
|
811
|
+
def delete_engine(self, name: str, type: str):
|
|
812
|
+
return self._engines.delete_engine(name, type)
|
|
821
813
|
|
|
822
|
-
def suspend_engine(self, name:str):
|
|
823
|
-
self.
|
|
814
|
+
def suspend_engine(self, name: str, type: str | None = None):
|
|
815
|
+
return self._engines.suspend_engine(name, type)
|
|
824
816
|
|
|
825
|
-
def resume_engine(self, name:str, headers: Dict | None = None) -> Dict:
|
|
826
|
-
|
|
827
|
-
self._exec(f"call {APP_NAME}.api.resume_engine('{name}',{request_headers});")
|
|
828
|
-
# returning empty dict to match the expected return type
|
|
829
|
-
return {}
|
|
817
|
+
def resume_engine(self, name: str, type: str | None = None, headers: Dict | None = None) -> Dict:
|
|
818
|
+
return self._engines.resume_engine(name, type=type, headers=headers)
|
|
830
819
|
|
|
831
|
-
def resume_engine_async(self, name:str, headers: Dict | None = None) -> Dict:
|
|
832
|
-
|
|
833
|
-
headers = {}
|
|
834
|
-
self._exec(f"call {APP_NAME}.api.resume_engine_async('{name}',{headers});")
|
|
835
|
-
# returning empty dict to match the expected return type
|
|
836
|
-
return {}
|
|
820
|
+
def resume_engine_async(self, name: str, type: str | None = None, headers: Dict | None = None) -> Dict:
|
|
821
|
+
return self._engines.resume_engine_async(name, type=type, headers=headers)
|
|
837
822
|
|
|
838
823
|
def alter_engine_pool(self, size:str|None=None, mins:int|None=None, maxs:int|None=None):
|
|
839
824
|
"""Alter engine pool node limits for Snowflake."""
|
|
840
|
-
self.
|
|
825
|
+
return self._engines.alter_engine_pool(size=size, mins=mins, maxs=maxs)
|
|
841
826
|
|
|
842
827
|
#--------------------------------------------------
|
|
843
828
|
# Graphs
|
|
@@ -1871,11 +1856,17 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1871
1856
|
assert isinstance(user, str), f"current_user() must return a string, not {type(user)}"
|
|
1872
1857
|
return _sanitize_user_name(user)
|
|
1873
1858
|
|
|
1874
|
-
def is_engine_ready(self, engine_name: str):
|
|
1875
|
-
engine = self.get_engine(engine_name)
|
|
1859
|
+
def is_engine_ready(self, engine_name: str, type: str = EngineType.LOGIC):
|
|
1860
|
+
engine = self.get_engine(engine_name, type)
|
|
1876
1861
|
return engine and engine["state"] == "READY"
|
|
1877
1862
|
|
|
1878
|
-
def auto_create_engine(
|
|
1863
|
+
def auto_create_engine(
|
|
1864
|
+
self,
|
|
1865
|
+
name: str | None = None,
|
|
1866
|
+
type: str = EngineType.LOGIC,
|
|
1867
|
+
size: str | None = None,
|
|
1868
|
+
headers: Dict | None = None,
|
|
1869
|
+
):
|
|
1879
1870
|
"""Synchronously create/ensure an engine is ready, blocking until ready."""
|
|
1880
1871
|
with debugging.span("auto_create_engine", active=self._active_engine) as span:
|
|
1881
1872
|
active = self._get_active_engine()
|
|
@@ -1883,18 +1874,19 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1883
1874
|
return active
|
|
1884
1875
|
|
|
1885
1876
|
# Resolve and validate parameters
|
|
1886
|
-
|
|
1877
|
+
name, size = self._prepare_engine_params(name, size)
|
|
1887
1878
|
|
|
1888
1879
|
try:
|
|
1889
1880
|
# Get current engine state
|
|
1890
|
-
engine = self.get_engine(
|
|
1881
|
+
engine = self.get_engine(name, type)
|
|
1891
1882
|
if engine:
|
|
1892
1883
|
span.update(cast(dict, engine))
|
|
1893
1884
|
|
|
1894
1885
|
# Create context for state handling
|
|
1895
1886
|
context = EngineContext(
|
|
1896
|
-
|
|
1897
|
-
|
|
1887
|
+
name=name,
|
|
1888
|
+
size=size,
|
|
1889
|
+
type=type,
|
|
1898
1890
|
headers=headers,
|
|
1899
1891
|
requested_size=size,
|
|
1900
1892
|
span=span,
|
|
@@ -1904,12 +1896,14 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1904
1896
|
self._process_engine_state(engine, context, self._sync_engine_state_handlers)
|
|
1905
1897
|
|
|
1906
1898
|
except Exception as e:
|
|
1907
|
-
self._handle_engine_creation_errors(e,
|
|
1899
|
+
self._handle_engine_creation_errors(e, name)
|
|
1908
1900
|
|
|
1909
|
-
return
|
|
1901
|
+
return name
|
|
1910
1902
|
|
|
1911
|
-
def auto_create_engine_async(self, name: str | None = None):
|
|
1903
|
+
def auto_create_engine_async(self, name: str | None = None, type: str | None = None):
|
|
1912
1904
|
"""Asynchronously create/ensure an engine, returns immediately."""
|
|
1905
|
+
if type is None:
|
|
1906
|
+
type = EngineType.LOGIC
|
|
1913
1907
|
active = self._get_active_engine()
|
|
1914
1908
|
if active and (active == name or name is None):
|
|
1915
1909
|
return active
|
|
@@ -1920,16 +1914,17 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1920
1914
|
) as spinner:
|
|
1921
1915
|
with debugging.span("auto_create_engine_async", active=self._active_engine):
|
|
1922
1916
|
# Resolve and validate parameters (use_default_size=True for async)
|
|
1923
|
-
|
|
1917
|
+
name, size = self._prepare_engine_params(name, None, use_default_size=True)
|
|
1924
1918
|
|
|
1925
1919
|
try:
|
|
1926
1920
|
# Get current engine state
|
|
1927
|
-
engine = self.get_engine(
|
|
1921
|
+
engine = self.get_engine(name, type)
|
|
1928
1922
|
|
|
1929
1923
|
# Create context for state handling
|
|
1930
1924
|
context = EngineContext(
|
|
1931
|
-
|
|
1932
|
-
|
|
1925
|
+
name=name,
|
|
1926
|
+
size=size,
|
|
1927
|
+
type=type,
|
|
1933
1928
|
headers=None,
|
|
1934
1929
|
requested_size=None,
|
|
1935
1930
|
spinner=spinner,
|
|
@@ -1940,11 +1935,11 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1940
1935
|
|
|
1941
1936
|
except Exception as e:
|
|
1942
1937
|
spinner.update_messages({
|
|
1943
|
-
"finished_message": f"Failed to create engine {
|
|
1938
|
+
"finished_message": f"Failed to create engine {name}",
|
|
1944
1939
|
})
|
|
1945
|
-
self._handle_engine_creation_errors(e,
|
|
1940
|
+
self._handle_engine_creation_errors(e, name, preserve_rai_exception=True)
|
|
1946
1941
|
|
|
1947
|
-
return
|
|
1942
|
+
return name
|
|
1948
1943
|
|
|
1949
1944
|
#--------------------------------------------------
|
|
1950
1945
|
# Exec
|
relationalai/clients/types.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
from abc import ABC
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from typing import Any, Optional, TypedDict
|
|
5
|
+
from typing_extensions import NotRequired
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from urllib.parse import urlparse
|
|
7
8
|
|
|
@@ -27,6 +28,7 @@ class AvailableModel(TypedDict):
|
|
|
27
28
|
|
|
28
29
|
class EngineState(TypedDict):
|
|
29
30
|
name: str
|
|
31
|
+
type: str
|
|
30
32
|
id: str
|
|
31
33
|
size: str
|
|
32
34
|
state: str
|
|
@@ -38,6 +40,9 @@ class EngineState(TypedDict):
|
|
|
38
40
|
auto_suspend: int|None
|
|
39
41
|
suspends_at: datetime|None
|
|
40
42
|
|
|
43
|
+
# Optional JSON settings (engine configuration)
|
|
44
|
+
settings: NotRequired[dict | None]
|
|
45
|
+
|
|
41
46
|
class SourceInfo(TypedDict, total=False):
|
|
42
47
|
type: str|None
|
|
43
48
|
state: str
|
relationalai/errors.py
CHANGED
|
@@ -1780,7 +1780,7 @@ class SnowflakeRaiAppNotStarted(RAIException):
|
|
|
1780
1780
|
def __init__(self, app_name: str):
|
|
1781
1781
|
self.app_name = app_name
|
|
1782
1782
|
self.message = f"The RelationalAI app '{app_name}' isn't started."
|
|
1783
|
-
self.name = "The RelationalAI application
|
|
1783
|
+
self.name = "The RelationalAI application isn't running"
|
|
1784
1784
|
self.content = self.format_message()
|
|
1785
1785
|
|
|
1786
1786
|
super().__init__(self.message, self.name, self.content)
|
|
@@ -1361,6 +1361,9 @@ class Replacer(visitor.Rewriter):
|
|
|
1361
1361
|
# Typer pass
|
|
1362
1362
|
#--------------------------------------------------
|
|
1363
1363
|
|
|
1364
|
+
# global flag to suppress type errors from being printed
|
|
1365
|
+
SUPPRESS_TYPE_ERRORS = False
|
|
1366
|
+
|
|
1364
1367
|
class InferTypes(compiler.Pass):
|
|
1365
1368
|
def __init__(self):
|
|
1366
1369
|
super().__init__()
|
|
@@ -1389,7 +1392,8 @@ class InferTypes(compiler.Pass):
|
|
|
1389
1392
|
with debugging.span("type.replace"):
|
|
1390
1393
|
final = Replacer(w.net).walk(model)
|
|
1391
1394
|
|
|
1392
|
-
|
|
1393
|
-
|
|
1395
|
+
if not SUPPRESS_TYPE_ERRORS:
|
|
1396
|
+
for err in w.net.errors:
|
|
1397
|
+
rich.print(str(err), file=sys.stderr)
|
|
1394
1398
|
|
|
1395
1399
|
return final
|