arize 8.0.0b0__py3-none-any.whl → 8.0.0b2__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.
- arize/__init__.py +1 -1
- arize/_client_factory.py +50 -0
- arize/_flight/client.py +4 -4
- arize/_generated/api_client/__init__.py +0 -2
- arize/_generated/api_client/api/datasets_api.py +6 -6
- arize/_generated/api_client/api/experiments_api.py +6 -6
- arize/_generated/api_client/api/projects_api.py +3 -3
- arize/_generated/api_client/models/__init__.py +0 -1
- arize/_generated/api_client/models/datasets_create_request.py +2 -10
- arize/_generated/api_client/models/datasets_examples_insert_request.py +2 -10
- arize/_generated/api_client/test/test_datasets_create_request.py +2 -6
- arize/_generated/api_client/test/test_datasets_examples_insert_request.py +2 -6
- arize/_generated/api_client/test/test_datasets_examples_list200_response.py +2 -6
- arize/_generated/api_client/test/test_datasets_examples_update_request.py +2 -6
- arize/_generated/api_client/test/test_experiments_create_request.py +2 -6
- arize/_generated/api_client/test/test_experiments_runs_list200_response.py +2 -6
- arize/_generated/api_client_README.md +0 -1
- arize/_lazy.py +25 -9
- arize/client.py +16 -52
- arize/config.py +9 -36
- arize/constants/ml.py +9 -16
- arize/constants/spans.py +5 -10
- arize/datasets/client.py +13 -9
- arize/datasets/errors.py +1 -1
- arize/datasets/validation.py +2 -2
- arize/embeddings/auto_generator.py +2 -2
- arize/embeddings/errors.py +2 -2
- arize/embeddings/tabular_generators.py +1 -1
- arize/exceptions/base.py +0 -52
- arize/exceptions/parameters.py +0 -329
- arize/experiments/__init__.py +2 -2
- arize/experiments/client.py +16 -10
- arize/experiments/evaluators/base.py +6 -6
- arize/experiments/evaluators/executors.py +10 -3
- arize/experiments/evaluators/types.py +2 -2
- arize/experiments/functions.py +24 -17
- arize/experiments/types.py +6 -8
- arize/logging.py +1 -1
- arize/ml/batch_validation/errors.py +10 -1004
- arize/ml/batch_validation/validator.py +273 -225
- arize/ml/casting.py +7 -7
- arize/ml/client.py +12 -11
- arize/ml/proto.py +6 -6
- arize/ml/stream_validation.py +2 -3
- arize/ml/surrogate_explainer/mimic.py +3 -3
- arize/ml/types.py +1 -55
- arize/pre_releases.py +6 -3
- arize/projects/client.py +9 -4
- arize/regions.py +2 -2
- arize/spans/client.py +14 -12
- arize/spans/columns.py +32 -36
- arize/spans/conversion.py +5 -6
- arize/spans/validation/common/argument_validation.py +3 -3
- arize/spans/validation/common/dataframe_form_validation.py +6 -6
- arize/spans/validation/common/value_validation.py +1 -1
- arize/spans/validation/evals/dataframe_form_validation.py +4 -4
- arize/spans/validation/evals/evals_validation.py +6 -6
- arize/spans/validation/metadata/dataframe_form_validation.py +1 -1
- arize/spans/validation/spans/dataframe_form_validation.py +2 -2
- arize/spans/validation/spans/spans_validation.py +6 -6
- arize/utils/arrow.py +2 -2
- arize/utils/cache.py +2 -2
- arize/utils/dataframe.py +4 -4
- arize/utils/online_tasks/dataframe_preprocessor.py +7 -7
- arize/utils/openinference_conversion.py +10 -10
- arize/utils/proto.py +1 -1
- arize/version.py +1 -1
- {arize-8.0.0b0.dist-info → arize-8.0.0b2.dist-info}/METADATA +71 -63
- {arize-8.0.0b0.dist-info → arize-8.0.0b2.dist-info}/RECORD +72 -73
- arize/_generated/api_client/models/primitive_value.py +0 -172
- arize/_generated/api_client/test/test_primitive_value.py +0 -50
- {arize-8.0.0b0.dist-info → arize-8.0.0b2.dist-info}/WHEEL +0 -0
- {arize-8.0.0b0.dist-info → arize-8.0.0b2.dist-info}/licenses/LICENSE +0 -0
- {arize-8.0.0b0.dist-info → arize-8.0.0b2.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
"""Batch validation error classes for ML model data.
|
|
1
|
+
"""Batch validation error classes for ML model data.
|
|
2
|
+
|
|
3
|
+
This module contains exceptions that are specific to batch validation logic.
|
|
4
|
+
For common validation exceptions, use:
|
|
5
|
+
- arize.exceptions.base (ValidationError, InvalidDataFrameIndex, etc.)
|
|
6
|
+
- arize.exceptions.types (InvalidType, InvalidTypeColumns, etc.)
|
|
7
|
+
- arize.exceptions.values (InvalidValueTimestamp, InvalidStringLengthInColumn, etc.)
|
|
8
|
+
"""
|
|
2
9
|
|
|
3
10
|
from __future__ import annotations
|
|
4
11
|
|
|
5
|
-
from abc import ABC, abstractmethod
|
|
6
12
|
from typing import TYPE_CHECKING
|
|
7
13
|
|
|
8
|
-
from arize.constants.ml import
|
|
9
|
-
|
|
10
|
-
MAX_FUTURE_YEARS_FROM_CURRENT_TIME,
|
|
11
|
-
MAX_MULTI_CLASS_NAME_LENGTH,
|
|
12
|
-
MAX_NUMBER_OF_EMBEDDINGS,
|
|
13
|
-
MAX_NUMBER_OF_MULTI_CLASS_CLASSES,
|
|
14
|
-
MAX_PAST_YEARS_FROM_CURRENT_TIME,
|
|
15
|
-
MAX_RAW_DATA_CHARACTERS,
|
|
16
|
-
MAX_TAG_LENGTH,
|
|
17
|
-
)
|
|
14
|
+
from arize.constants.ml import MAX_NUMBER_OF_EMBEDDINGS
|
|
15
|
+
from arize.exceptions.base import ValidationError
|
|
18
16
|
from arize.logging import log_a_list
|
|
19
17
|
from arize.ml.types import Environments, ModelTypes
|
|
20
18
|
|
|
@@ -24,34 +22,6 @@ if TYPE_CHECKING:
|
|
|
24
22
|
from arize.ml.types import Metrics
|
|
25
23
|
|
|
26
24
|
|
|
27
|
-
class ValidationError(Exception, ABC):
|
|
28
|
-
"""Base class for validation errors during batch data ingestion."""
|
|
29
|
-
|
|
30
|
-
def __str__(self) -> str:
|
|
31
|
-
"""Return a human-readable error message."""
|
|
32
|
-
return self.error_message()
|
|
33
|
-
|
|
34
|
-
@abstractmethod
|
|
35
|
-
def __repr__(self) -> str:
|
|
36
|
-
"""Return a string representation for debugging and logging."""
|
|
37
|
-
|
|
38
|
-
@abstractmethod
|
|
39
|
-
def error_message(self) -> str:
|
|
40
|
-
"""Return the error message for this exception."""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class ValidationFailure(Exception):
|
|
44
|
-
"""Raised when validation encounters multiple errors during processing."""
|
|
45
|
-
|
|
46
|
-
def __init__(self, errors: list[ValidationError]) -> None:
|
|
47
|
-
"""Initialize the exception with a list of validation errors.
|
|
48
|
-
|
|
49
|
-
Args:
|
|
50
|
-
errors: List of validation errors encountered during processing.
|
|
51
|
-
"""
|
|
52
|
-
self.errors = errors
|
|
53
|
-
|
|
54
|
-
|
|
55
25
|
# ----------------------
|
|
56
26
|
# Minimum required checks
|
|
57
27
|
# ----------------------
|
|
@@ -71,31 +41,6 @@ class InvalidColumnNameEmptyString(ValidationError):
|
|
|
71
41
|
)
|
|
72
42
|
|
|
73
43
|
|
|
74
|
-
class InvalidFieldTypeConversion(ValidationError):
|
|
75
|
-
"""Raised when field values cannot be converted to the required type."""
|
|
76
|
-
|
|
77
|
-
def __repr__(self) -> str:
|
|
78
|
-
"""Return a string representation for debugging and logging."""
|
|
79
|
-
return "Invalid_Input_Type_Conversion"
|
|
80
|
-
|
|
81
|
-
def __init__(self, fields: Iterable, type: str) -> None:
|
|
82
|
-
"""Initialize the exception with field type conversion context.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
fields: Fields that failed type conversion.
|
|
86
|
-
type: Expected type for the fields.
|
|
87
|
-
"""
|
|
88
|
-
self.fields = fields
|
|
89
|
-
self.type = type
|
|
90
|
-
|
|
91
|
-
def error_message(self) -> str:
|
|
92
|
-
"""Return the error message for this exception."""
|
|
93
|
-
return (
|
|
94
|
-
f"The following fields must be convertible to {self.type}: "
|
|
95
|
-
f"{', '.join(map(str, self.fields))}."
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
|
|
99
44
|
class InvalidFieldTypeEmbeddingFeatures(ValidationError):
|
|
100
45
|
"""Raised when embedding feature column names are not properly formatted."""
|
|
101
46
|
|
|
@@ -134,21 +79,6 @@ class InvalidFieldTypePromptResponse(ValidationError):
|
|
|
134
79
|
return f"'{self.name}' must be of type str or EmbeddingColumnNames"
|
|
135
80
|
|
|
136
81
|
|
|
137
|
-
class InvalidDataFrameIndex(ValidationError):
|
|
138
|
-
"""Raised when the dataframe index is invalid and needs to be reset."""
|
|
139
|
-
|
|
140
|
-
def __repr__(self) -> str:
|
|
141
|
-
"""Return a string representation for debugging and logging."""
|
|
142
|
-
return "Invalid_Index"
|
|
143
|
-
|
|
144
|
-
def error_message(self) -> str:
|
|
145
|
-
"""Return the error message for this exception."""
|
|
146
|
-
return (
|
|
147
|
-
"The index of the dataframe is invalid; "
|
|
148
|
-
"reset the index by using df.reset_index(drop=True, inplace=True)"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
82
|
class InvalidSchemaType(ValidationError):
|
|
153
83
|
"""Raised when schema type is incompatible with the model environment."""
|
|
154
84
|
|
|
@@ -697,927 +627,3 @@ class InvalidNumberOfEmbeddings(ValidationError):
|
|
|
697
627
|
f"The schema contains {self.number_of_embeddings} different embeddings when a maximum of "
|
|
698
628
|
f"{MAX_NUMBER_OF_EMBEDDINGS} is allowed."
|
|
699
629
|
)
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
# -----------
|
|
703
|
-
# Type checks
|
|
704
|
-
# -----------
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
class InvalidType(ValidationError):
|
|
708
|
-
"""Raised when a field has an invalid data type."""
|
|
709
|
-
|
|
710
|
-
def __repr__(self) -> str:
|
|
711
|
-
"""Return a string representation for debugging and logging."""
|
|
712
|
-
return "Invalid_Type"
|
|
713
|
-
|
|
714
|
-
def __init__(
|
|
715
|
-
self, name: str, expected_types: list[str], found_data_type: str
|
|
716
|
-
) -> None:
|
|
717
|
-
"""Initialize the exception with type validation context.
|
|
718
|
-
|
|
719
|
-
Args:
|
|
720
|
-
name: Name of the field with invalid type.
|
|
721
|
-
expected_types: List of expected data types.
|
|
722
|
-
found_data_type: Actual data type found.
|
|
723
|
-
"""
|
|
724
|
-
self.name = name
|
|
725
|
-
self.expected_types = expected_types
|
|
726
|
-
self.found_data_type = found_data_type
|
|
727
|
-
|
|
728
|
-
def error_message(self) -> str:
|
|
729
|
-
"""Return the error message for this exception."""
|
|
730
|
-
type_list = (
|
|
731
|
-
self.expected_types[0]
|
|
732
|
-
if len(self.expected_types) == 1
|
|
733
|
-
else f"{', '.join(map(str, self.expected_types[:-1]))} or {self.expected_types[-1]}"
|
|
734
|
-
)
|
|
735
|
-
return (
|
|
736
|
-
f"{self.name} must be of type {type_list} but found {self.found_data_type}. "
|
|
737
|
-
"Warning: if you are sending a column with integers, presence of a null "
|
|
738
|
-
"value can convert the data type of the entire column to float."
|
|
739
|
-
)
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
class InvalidTypeColumns(ValidationError):
|
|
743
|
-
"""Raised when columns have invalid data types."""
|
|
744
|
-
|
|
745
|
-
def __repr__(self) -> str:
|
|
746
|
-
"""Return a string representation for debugging and logging."""
|
|
747
|
-
return "Invalid_Type_Columns"
|
|
748
|
-
|
|
749
|
-
def __init__(
|
|
750
|
-
self, wrong_type_columns: list[str], expected_types: list[str]
|
|
751
|
-
) -> None:
|
|
752
|
-
"""Initialize the exception with column type validation context.
|
|
753
|
-
|
|
754
|
-
Args:
|
|
755
|
-
wrong_type_columns: Columns with incorrect data types.
|
|
756
|
-
expected_types: List of expected data types for the columns.
|
|
757
|
-
"""
|
|
758
|
-
self.wrong_type_columns = wrong_type_columns
|
|
759
|
-
self.expected_types = expected_types
|
|
760
|
-
|
|
761
|
-
def error_message(self) -> str:
|
|
762
|
-
"""Return the error message for this exception."""
|
|
763
|
-
col_list = (
|
|
764
|
-
self.wrong_type_columns[0]
|
|
765
|
-
if len(self.wrong_type_columns) == 1
|
|
766
|
-
else f"{', '.join(self.wrong_type_columns[:-1])}, and {self.wrong_type_columns[-1]}"
|
|
767
|
-
)
|
|
768
|
-
type_list = (
|
|
769
|
-
self.expected_types[0]
|
|
770
|
-
if len(self.expected_types) == 1
|
|
771
|
-
else f"{', '.join(map(str, self.expected_types[:-1]))} or {self.expected_types[-1]}"
|
|
772
|
-
)
|
|
773
|
-
return f"The column(s) {col_list}; must be of type {type_list}."
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
class InvalidTypeFeatures(ValidationError):
|
|
777
|
-
"""Raised when feature columns have unrecognized data types."""
|
|
778
|
-
|
|
779
|
-
def __repr__(self) -> str:
|
|
780
|
-
"""Return a string representation for debugging and logging."""
|
|
781
|
-
return "Invalid_Type_Features"
|
|
782
|
-
|
|
783
|
-
def __init__(self, cols: Iterable, expected_types: list[str]) -> None:
|
|
784
|
-
"""Initialize the exception with feature type validation context.
|
|
785
|
-
|
|
786
|
-
Args:
|
|
787
|
-
cols: Feature columns with unrecognized data types.
|
|
788
|
-
expected_types: List of expected data types for features.
|
|
789
|
-
"""
|
|
790
|
-
self.wrong_type_columns = cols
|
|
791
|
-
self.expected_types = expected_types
|
|
792
|
-
|
|
793
|
-
def error_message(self) -> str:
|
|
794
|
-
"""Return the error message for this exception."""
|
|
795
|
-
type_list = (
|
|
796
|
-
self.expected_types[0]
|
|
797
|
-
if len(self.expected_types) == 1
|
|
798
|
-
else f"{', '.join(map(str, self.expected_types[:-1]))} or {self.expected_types[-1]}"
|
|
799
|
-
)
|
|
800
|
-
return (
|
|
801
|
-
f"Features must be of type {type_list}. "
|
|
802
|
-
"The following feature columns have unrecognized data types: "
|
|
803
|
-
f"{', '.join(map(str, self.wrong_type_columns))}."
|
|
804
|
-
)
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
class InvalidFieldTypePromptTemplates(ValidationError):
|
|
808
|
-
"""Raised when prompt template column names are not of correct type."""
|
|
809
|
-
|
|
810
|
-
def __repr__(self) -> str:
|
|
811
|
-
"""Return a string representation for debugging and logging."""
|
|
812
|
-
return "Invalid_Input_Type_Prompt_Templates"
|
|
813
|
-
|
|
814
|
-
def error_message(self) -> str:
|
|
815
|
-
"""Return the error message for this exception."""
|
|
816
|
-
return "prompt_template_column_names must be of type PromptTemplateColumnNames"
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
class InvalidFieldTypeLlmConfig(ValidationError):
|
|
820
|
-
"""Raised when LLM config column names are not of correct type."""
|
|
821
|
-
|
|
822
|
-
def __repr__(self) -> str:
|
|
823
|
-
"""Return a string representation for debugging and logging."""
|
|
824
|
-
return "Invalid_Input_Type_LLM_Config"
|
|
825
|
-
|
|
826
|
-
def error_message(self) -> str:
|
|
827
|
-
"""Return the error message for this exception."""
|
|
828
|
-
return "llm_config_column_names must be of type LLMConfigColumnNames"
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
class InvalidTypeTags(ValidationError):
|
|
832
|
-
"""Raised when tag columns have unrecognized data types."""
|
|
833
|
-
|
|
834
|
-
def __repr__(self) -> str:
|
|
835
|
-
"""Return a string representation for debugging and logging."""
|
|
836
|
-
return "Invalid_Type_Tags"
|
|
837
|
-
|
|
838
|
-
def __init__(self, cols: Iterable, expected_types: list[str]) -> None:
|
|
839
|
-
"""Initialize the exception with tag type validation context.
|
|
840
|
-
|
|
841
|
-
Args:
|
|
842
|
-
cols: Tag columns with unrecognized data types.
|
|
843
|
-
expected_types: List of expected data types for tags.
|
|
844
|
-
"""
|
|
845
|
-
self.wrong_type_columns = cols
|
|
846
|
-
self.expected_types = expected_types
|
|
847
|
-
|
|
848
|
-
def error_message(self) -> str:
|
|
849
|
-
"""Return the error message for this exception."""
|
|
850
|
-
type_list = (
|
|
851
|
-
self.expected_types[0]
|
|
852
|
-
if len(self.expected_types) == 1
|
|
853
|
-
else f"{', '.join(map(str, self.expected_types[:-1]))} or {self.expected_types[-1]}"
|
|
854
|
-
)
|
|
855
|
-
return (
|
|
856
|
-
f"Tags must be of type {type_list}. "
|
|
857
|
-
"The following tag columns have unrecognized data types: "
|
|
858
|
-
f"{', '.join(map(str, self.wrong_type_columns))}."
|
|
859
|
-
)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
class InvalidValueEmbeddingVectorDimensionality(ValidationError):
|
|
863
|
-
"""Raised when embedding vector dimensionality is out of valid range."""
|
|
864
|
-
|
|
865
|
-
def __repr__(self) -> str:
|
|
866
|
-
"""Return a string representation for debugging and logging."""
|
|
867
|
-
return "Invalid_Value_Embedding_Vector_Dimensionality"
|
|
868
|
-
|
|
869
|
-
def __init__(self, dim_1_cols: list[str], high_dim_cols: list[str]) -> None:
|
|
870
|
-
"""Initialize the exception with embedding dimensionality context.
|
|
871
|
-
|
|
872
|
-
Args:
|
|
873
|
-
dim_1_cols: Columns with dimensionality of 1.
|
|
874
|
-
high_dim_cols: Columns with dimensionality exceeding the maximum.
|
|
875
|
-
"""
|
|
876
|
-
self.dim_1_cols = dim_1_cols
|
|
877
|
-
self.high_dim_cols = high_dim_cols
|
|
878
|
-
|
|
879
|
-
def error_message(self) -> str:
|
|
880
|
-
"""Return the error message for this exception."""
|
|
881
|
-
msg = (
|
|
882
|
-
"Embedding vectors cannot have length (dimensionality) of 1 or higher "
|
|
883
|
-
f"than {MAX_EMBEDDING_DIMENSIONALITY}. "
|
|
884
|
-
)
|
|
885
|
-
if self.dim_1_cols:
|
|
886
|
-
msg += f"The following columns have dimensionality of 1: {','.join(self.dim_1_cols)}. "
|
|
887
|
-
if self.high_dim_cols:
|
|
888
|
-
msg += (
|
|
889
|
-
f"The following columns have dimensionality greater than {MAX_EMBEDDING_DIMENSIONALITY}: "
|
|
890
|
-
f"{','.join(self.high_dim_cols)}. "
|
|
891
|
-
)
|
|
892
|
-
|
|
893
|
-
return msg
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
class InvalidValueEmbeddingRawDataTooLong(ValidationError):
|
|
897
|
-
"""Raised when embedding raw data exceeds maximum character limit."""
|
|
898
|
-
|
|
899
|
-
def __repr__(self) -> str:
|
|
900
|
-
"""Return a string representation for debugging and logging."""
|
|
901
|
-
return "Invalid_Value_Embedding_Raw_Data_Too_Long"
|
|
902
|
-
|
|
903
|
-
def __init__(self, cols: Iterable) -> None:
|
|
904
|
-
"""Initialize the exception with raw data length validation context.
|
|
905
|
-
|
|
906
|
-
Args:
|
|
907
|
-
cols: Columns with embedding raw data exceeding maximum characters.
|
|
908
|
-
"""
|
|
909
|
-
self.invalid_cols = cols
|
|
910
|
-
|
|
911
|
-
def error_message(self) -> str:
|
|
912
|
-
"""Return the error message for this exception."""
|
|
913
|
-
return (
|
|
914
|
-
f"Embedding raw data cannot have more than {MAX_RAW_DATA_CHARACTERS} characters. "
|
|
915
|
-
"The following columns do not satisfy this condition: "
|
|
916
|
-
f"{', '.join(map(str, self.invalid_cols))}."
|
|
917
|
-
)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
class InvalidTypeShapValues(ValidationError):
|
|
921
|
-
"""Raised when SHAP value columns have unrecognized data types."""
|
|
922
|
-
|
|
923
|
-
def __repr__(self) -> str:
|
|
924
|
-
"""Return a string representation for debugging and logging."""
|
|
925
|
-
return "Invalid_Type_SHAP_Values"
|
|
926
|
-
|
|
927
|
-
def __init__(self, cols: Iterable, expected_types: list[str]) -> None:
|
|
928
|
-
"""Initialize the exception with SHAP value type validation context.
|
|
929
|
-
|
|
930
|
-
Args:
|
|
931
|
-
cols: SHAP value columns with unrecognized data types.
|
|
932
|
-
expected_types: List of expected data types for SHAP values.
|
|
933
|
-
"""
|
|
934
|
-
self.wrong_type_columns = cols
|
|
935
|
-
self.expected_types = expected_types
|
|
936
|
-
|
|
937
|
-
def error_message(self) -> str:
|
|
938
|
-
"""Return the error message for this exception."""
|
|
939
|
-
type_list = (
|
|
940
|
-
self.expected_types[0]
|
|
941
|
-
if len(self.expected_types) == 1
|
|
942
|
-
else f"{', '.join(map(str, self.expected_types[:-1]))} or {self.expected_types[-1]}"
|
|
943
|
-
)
|
|
944
|
-
return (
|
|
945
|
-
f"SHAP values must be of type {type_list}. "
|
|
946
|
-
"The following SHAP columns have unrecognized data types: "
|
|
947
|
-
f"{', '.join(map(str, self.wrong_type_columns))}."
|
|
948
|
-
)
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
# -----------
|
|
952
|
-
# Value checks
|
|
953
|
-
# -----------
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
class InvalidValueTimestamp(ValidationError):
|
|
957
|
-
"""Raised when timestamp values are outside acceptable time range."""
|
|
958
|
-
|
|
959
|
-
def __repr__(self) -> str:
|
|
960
|
-
"""Return a string representation for debugging and logging."""
|
|
961
|
-
return "Invalid_Timestamp_Value"
|
|
962
|
-
|
|
963
|
-
def __init__(self, timestamp_col_name: str) -> None:
|
|
964
|
-
"""Initialize the exception with timestamp validation context.
|
|
965
|
-
|
|
966
|
-
Args:
|
|
967
|
-
timestamp_col_name: Name of the column containing invalid timestamp values.
|
|
968
|
-
"""
|
|
969
|
-
self.timestamp_col_name = timestamp_col_name
|
|
970
|
-
|
|
971
|
-
def error_message(self) -> str:
|
|
972
|
-
"""Return the error message for this exception."""
|
|
973
|
-
return (
|
|
974
|
-
f"Prediction timestamp in {self.timestamp_col_name} is out of range. "
|
|
975
|
-
f"Prediction timestamps must be within {MAX_FUTURE_YEARS_FROM_CURRENT_TIME} year "
|
|
976
|
-
f"in the future and {MAX_PAST_YEARS_FROM_CURRENT_TIME} years in the past from "
|
|
977
|
-
"the current time. If this is your pre-production data, you could also just "
|
|
978
|
-
"remove the timestamp column from the Schema."
|
|
979
|
-
)
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
class InvalidValueMissingValue(ValidationError):
|
|
983
|
-
"""Raised when required fields contain null or missing values."""
|
|
984
|
-
|
|
985
|
-
def __repr__(self) -> str:
|
|
986
|
-
"""Return a string representation for debugging and logging."""
|
|
987
|
-
return "Invalid_Missing_Value"
|
|
988
|
-
|
|
989
|
-
def __init__(
|
|
990
|
-
self, name: str, wrong_values: str, column: str | None = None
|
|
991
|
-
) -> None:
|
|
992
|
-
"""Initialize the exception with missing value validation context.
|
|
993
|
-
|
|
994
|
-
Args:
|
|
995
|
-
name: Name of the field with missing values.
|
|
996
|
-
wrong_values: Description of the wrong values found (e.g., "null", "NaN").
|
|
997
|
-
column: Optional column name where missing values were found.
|
|
998
|
-
"""
|
|
999
|
-
self.name = name
|
|
1000
|
-
self.wrong_values = wrong_values
|
|
1001
|
-
self.column = column
|
|
1002
|
-
|
|
1003
|
-
def error_message(self) -> str:
|
|
1004
|
-
"""Return the error message for this exception."""
|
|
1005
|
-
if self.name in ["Prediction ID", "Prediction Group ID", "Rank"]:
|
|
1006
|
-
return f"{self.name} column '{self.column}' must not contain {self.wrong_values} values."
|
|
1007
|
-
return f"{self.name} must not contain {self.wrong_values} values."
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
class InvalidRankValue(ValidationError):
|
|
1011
|
-
"""Raised when ranking column values are outside acceptable range."""
|
|
1012
|
-
|
|
1013
|
-
def __repr__(self) -> str:
|
|
1014
|
-
"""Return a string representation for debugging and logging."""
|
|
1015
|
-
return "Invalid_Rank_Value"
|
|
1016
|
-
|
|
1017
|
-
def __init__(self, name: str, acceptable_range: str) -> None:
|
|
1018
|
-
"""Initialize the exception with rank validation context.
|
|
1019
|
-
|
|
1020
|
-
Args:
|
|
1021
|
-
name: Name of the ranking column.
|
|
1022
|
-
acceptable_range: Description of the acceptable value range.
|
|
1023
|
-
"""
|
|
1024
|
-
self.name = name
|
|
1025
|
-
self.acceptable_range = acceptable_range
|
|
1026
|
-
|
|
1027
|
-
def error_message(self) -> str:
|
|
1028
|
-
"""Return the error message for this exception."""
|
|
1029
|
-
return (
|
|
1030
|
-
f"ranking column {self.name} is out of range. "
|
|
1031
|
-
f"Only values within {self.acceptable_range} are accepted."
|
|
1032
|
-
)
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
class InvalidStringLengthInColumn(ValidationError):
|
|
1036
|
-
"""Raised when string values in a column exceed length limits."""
|
|
1037
|
-
|
|
1038
|
-
def __repr__(self) -> str:
|
|
1039
|
-
"""Return a string representation for debugging and logging."""
|
|
1040
|
-
return "Invalid_String_Length_In_Column"
|
|
1041
|
-
|
|
1042
|
-
def __init__(
|
|
1043
|
-
self, schema_name: str, col_name: str, min_length: int, max_length: int
|
|
1044
|
-
) -> None:
|
|
1045
|
-
"""Initialize the exception with string length validation context.
|
|
1046
|
-
|
|
1047
|
-
Args:
|
|
1048
|
-
schema_name: Name of the schema field.
|
|
1049
|
-
col_name: Name of the column with invalid string lengths.
|
|
1050
|
-
min_length: Minimum acceptable string length.
|
|
1051
|
-
max_length: Maximum acceptable string length.
|
|
1052
|
-
"""
|
|
1053
|
-
self.schema_name = schema_name
|
|
1054
|
-
self.col_name = col_name
|
|
1055
|
-
self.min_length = min_length
|
|
1056
|
-
self.max_length = max_length
|
|
1057
|
-
|
|
1058
|
-
def error_message(self) -> str:
|
|
1059
|
-
"""Return the error message for this exception."""
|
|
1060
|
-
return (
|
|
1061
|
-
f"{self.schema_name} column '{self.col_name}' contains invalid values. "
|
|
1062
|
-
f"Only string values of length between {self.min_length} and {self.max_length} are accepted."
|
|
1063
|
-
)
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
class InvalidTagLength(ValidationError):
|
|
1067
|
-
"""Raised when tag values exceed maximum character length."""
|
|
1068
|
-
|
|
1069
|
-
def __repr__(self) -> str:
|
|
1070
|
-
"""Return a string representation for debugging and logging."""
|
|
1071
|
-
return "Invalid_Tag_Length"
|
|
1072
|
-
|
|
1073
|
-
def __init__(self, cols: Iterable) -> None:
|
|
1074
|
-
"""Initialize the exception with tag length validation context.
|
|
1075
|
-
|
|
1076
|
-
Args:
|
|
1077
|
-
cols: Tag columns with values exceeding maximum character length.
|
|
1078
|
-
"""
|
|
1079
|
-
self.wrong_value_columns = cols
|
|
1080
|
-
|
|
1081
|
-
def error_message(self) -> str:
|
|
1082
|
-
"""Return the error message for this exception."""
|
|
1083
|
-
return (
|
|
1084
|
-
f"Only tag values with less than or equal to {MAX_TAG_LENGTH} characters are supported. "
|
|
1085
|
-
f"The following tag columns have more than {MAX_TAG_LENGTH} characters: "
|
|
1086
|
-
f"{', '.join(map(str, self.wrong_value_columns))}."
|
|
1087
|
-
)
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
class InvalidRankingCategoryValue(ValidationError):
|
|
1091
|
-
"""Raised when ranking relevance labels contain invalid values."""
|
|
1092
|
-
|
|
1093
|
-
def __repr__(self) -> str:
|
|
1094
|
-
"""Return a string representation for debugging and logging."""
|
|
1095
|
-
return "Invalid_Ranking_Relevance_Labels_Value"
|
|
1096
|
-
|
|
1097
|
-
def __init__(self, name: str) -> None:
|
|
1098
|
-
"""Initialize the exception with ranking category validation context.
|
|
1099
|
-
|
|
1100
|
-
Args:
|
|
1101
|
-
name: Name of the ranking relevance labels column.
|
|
1102
|
-
"""
|
|
1103
|
-
self.name = name
|
|
1104
|
-
|
|
1105
|
-
def error_message(self) -> str:
|
|
1106
|
-
"""Return the error message for this exception."""
|
|
1107
|
-
return (
|
|
1108
|
-
f"Ranking relevance labels '{self.name}' column contains invalid value. "
|
|
1109
|
-
f"Make sure empty string is not present"
|
|
1110
|
-
)
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
class InvalidBoundingBoxesCoordinates(ValidationError, Exception):
|
|
1114
|
-
"""Raised when bounding box coordinates are invalid or incorrectly formatted."""
|
|
1115
|
-
|
|
1116
|
-
def __repr__(self) -> str:
|
|
1117
|
-
"""Return a string representation for debugging and logging."""
|
|
1118
|
-
return "Invalid_Bounding_Boxes_Coordinates"
|
|
1119
|
-
|
|
1120
|
-
def __init__(self, reason: str) -> None:
|
|
1121
|
-
"""Initialize the exception with bounding box coordinate validation context.
|
|
1122
|
-
|
|
1123
|
-
Args:
|
|
1124
|
-
reason: Specific reason for invalid coordinates (e.g., "none_boxes",
|
|
1125
|
-
"none_or_empty_box", "boxes_coordinates_wrong_format").
|
|
1126
|
-
"""
|
|
1127
|
-
self._check_valid_reason(reason)
|
|
1128
|
-
self.reason = reason
|
|
1129
|
-
|
|
1130
|
-
@staticmethod
|
|
1131
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1132
|
-
possible_reasons = (
|
|
1133
|
-
"none_boxes",
|
|
1134
|
-
"none_or_empty_box",
|
|
1135
|
-
"boxes_coordinates_wrong_format",
|
|
1136
|
-
)
|
|
1137
|
-
if reason not in possible_reasons:
|
|
1138
|
-
raise ValueError(
|
|
1139
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1140
|
-
f"{', '.join(possible_reasons)}."
|
|
1141
|
-
)
|
|
1142
|
-
|
|
1143
|
-
def error_message(self) -> str:
|
|
1144
|
-
"""Return the error message for this exception."""
|
|
1145
|
-
msg = "Invalid bounding boxes coordinates found. "
|
|
1146
|
-
if self.reason == "none_boxes":
|
|
1147
|
-
msg += (
|
|
1148
|
-
"Found at least one list of bounding boxes coordinates with NoneType. List of "
|
|
1149
|
-
"bounding boxes coordinates cannot be None, if you'd like to send no boxes, "
|
|
1150
|
-
"send an empty list"
|
|
1151
|
-
)
|
|
1152
|
-
elif self.reason == "none_or_empty_box":
|
|
1153
|
-
msg += (
|
|
1154
|
-
"Found at least one bounding box with None value or without coordinates. All "
|
|
1155
|
-
"bounding boxes in the list must contain its 4 coordinates"
|
|
1156
|
-
)
|
|
1157
|
-
elif self.reason == "boxes_coordinates_wrong_format":
|
|
1158
|
-
msg += (
|
|
1159
|
-
"Found at least one bound box's coordinates incorrectly formatted. Each "
|
|
1160
|
-
"bounding box's coordinates must be a collection of 4 positive floats "
|
|
1161
|
-
"representing the top-left & bottom-right corners of the box, in pixels"
|
|
1162
|
-
)
|
|
1163
|
-
return msg
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
class InvalidBoundingBoxesCategories(ValidationError, Exception):
|
|
1167
|
-
"""Raised when bounding box categories are invalid or missing."""
|
|
1168
|
-
|
|
1169
|
-
def __repr__(self) -> str:
|
|
1170
|
-
"""Return a string representation for debugging and logging."""
|
|
1171
|
-
return "Invalid_Bounding_Boxes_Categories"
|
|
1172
|
-
|
|
1173
|
-
def __init__(self, reason: str) -> None:
|
|
1174
|
-
"""Initialize the exception with bounding box category validation context.
|
|
1175
|
-
|
|
1176
|
-
Args:
|
|
1177
|
-
reason: Specific reason for invalid categories (e.g., "none_category_list",
|
|
1178
|
-
"none_category").
|
|
1179
|
-
"""
|
|
1180
|
-
self._check_valid_reason(reason)
|
|
1181
|
-
self.reason = reason
|
|
1182
|
-
|
|
1183
|
-
@staticmethod
|
|
1184
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1185
|
-
possible_reasons = (
|
|
1186
|
-
"none_category_list",
|
|
1187
|
-
"none_category",
|
|
1188
|
-
)
|
|
1189
|
-
if reason not in possible_reasons:
|
|
1190
|
-
raise ValueError(
|
|
1191
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1192
|
-
f"{', '.join(possible_reasons)}."
|
|
1193
|
-
)
|
|
1194
|
-
|
|
1195
|
-
def error_message(self) -> str:
|
|
1196
|
-
"""Return the error message for this exception."""
|
|
1197
|
-
msg = "Invalid bounding boxes categories found. "
|
|
1198
|
-
if self.reason == "none_category_list":
|
|
1199
|
-
msg += (
|
|
1200
|
-
"Found at least one list of bounding box categories with None value. Must send a "
|
|
1201
|
-
"list of categories, one category per bounding box."
|
|
1202
|
-
)
|
|
1203
|
-
elif self.reason == "none_category":
|
|
1204
|
-
msg += (
|
|
1205
|
-
"Found at least one category label with None value. Each bounding box category "
|
|
1206
|
-
"must be string. Empty strings are allowed"
|
|
1207
|
-
)
|
|
1208
|
-
return msg
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
class InvalidBoundingBoxesScores(ValidationError, Exception):
|
|
1212
|
-
"""Raised when bounding box confidence scores are invalid or out of bounds."""
|
|
1213
|
-
|
|
1214
|
-
def __repr__(self) -> str:
|
|
1215
|
-
"""Return a string representation for debugging and logging."""
|
|
1216
|
-
return "Invalid_Bounding_Boxes_Scores"
|
|
1217
|
-
|
|
1218
|
-
def __init__(self, reason: str) -> None:
|
|
1219
|
-
"""Initialize the exception with bounding box score validation context.
|
|
1220
|
-
|
|
1221
|
-
Args:
|
|
1222
|
-
reason: Specific reason for invalid scores (e.g., "none_score_list",
|
|
1223
|
-
"scores_out_of_bounds").
|
|
1224
|
-
"""
|
|
1225
|
-
self._check_valid_reason(reason)
|
|
1226
|
-
self.reason = reason
|
|
1227
|
-
|
|
1228
|
-
@staticmethod
|
|
1229
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1230
|
-
possible_reasons = (
|
|
1231
|
-
"none_score_list",
|
|
1232
|
-
"scores_out_of_bounds",
|
|
1233
|
-
)
|
|
1234
|
-
if reason not in possible_reasons:
|
|
1235
|
-
raise ValueError(
|
|
1236
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1237
|
-
f"{', '.join(possible_reasons)}."
|
|
1238
|
-
)
|
|
1239
|
-
|
|
1240
|
-
def error_message(self) -> str:
|
|
1241
|
-
"""Return the error message for this exception."""
|
|
1242
|
-
msg = "Invalid bounding boxes scores found. "
|
|
1243
|
-
if self.reason == "none_score_list":
|
|
1244
|
-
msg += (
|
|
1245
|
-
"Found at least one list of bounding box scores with None value. This field is "
|
|
1246
|
-
"optional. If sent, you must send a confidence score per bounding box"
|
|
1247
|
-
)
|
|
1248
|
-
elif self.reason == "scores_out_of_bounds":
|
|
1249
|
-
msg += (
|
|
1250
|
-
"Found at least one confidence score out of bounds. "
|
|
1251
|
-
"Confidence scores must be between 0 and 1"
|
|
1252
|
-
)
|
|
1253
|
-
return msg
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
class InvalidPolygonCoordinates(ValidationError, Exception):
|
|
1257
|
-
"""Raised when polygon coordinates are invalid or incorrectly formatted."""
|
|
1258
|
-
|
|
1259
|
-
def __repr__(self) -> str:
|
|
1260
|
-
"""Return a string representation for debugging and logging."""
|
|
1261
|
-
return "Invalid_Polygon_Coordinates"
|
|
1262
|
-
|
|
1263
|
-
def __init__(
|
|
1264
|
-
self, reason: str, coordinates: list[float] | None = None
|
|
1265
|
-
) -> None:
|
|
1266
|
-
"""Initialize the exception with polygon coordinate validation context.
|
|
1267
|
-
|
|
1268
|
-
Args:
|
|
1269
|
-
reason: Specific reason for invalid coordinates (e.g., "none_polygons",
|
|
1270
|
-
"none_or_empty_polygon", "polygon_coordinates_wrong_format").
|
|
1271
|
-
coordinates: Optional list of invalid coordinates for error reporting.
|
|
1272
|
-
"""
|
|
1273
|
-
self._check_valid_reason(reason)
|
|
1274
|
-
self.reason = reason
|
|
1275
|
-
self.coordinates = coordinates
|
|
1276
|
-
|
|
1277
|
-
@staticmethod
|
|
1278
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1279
|
-
possible_reasons = (
|
|
1280
|
-
"none_polygons",
|
|
1281
|
-
"none_or_empty_polygon",
|
|
1282
|
-
"polygon_coordinates_wrong_format",
|
|
1283
|
-
"polygon_coordinates_repeated_vertices",
|
|
1284
|
-
"polygon_coordinates_self_intersecting_vertices",
|
|
1285
|
-
)
|
|
1286
|
-
if reason not in possible_reasons:
|
|
1287
|
-
raise ValueError(
|
|
1288
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1289
|
-
f"{', '.join(possible_reasons)}."
|
|
1290
|
-
)
|
|
1291
|
-
|
|
1292
|
-
def error_message(self) -> str:
|
|
1293
|
-
"""Return the error message for this exception."""
|
|
1294
|
-
msg = "Invalid polygon coordinates found. "
|
|
1295
|
-
if self.reason == "none_polygons":
|
|
1296
|
-
msg += (
|
|
1297
|
-
"Found at least one list of polygon coordinates with NoneType. List of "
|
|
1298
|
-
"polygon coordinates cannot be None, if you'd like to send no coordinates, "
|
|
1299
|
-
"send an empty list"
|
|
1300
|
-
)
|
|
1301
|
-
elif self.reason == "none_or_empty_polygon":
|
|
1302
|
-
msg += (
|
|
1303
|
-
"Found at least one polygon with None value or without coordinates. All "
|
|
1304
|
-
"polygons in the list must contain its coordinates"
|
|
1305
|
-
)
|
|
1306
|
-
elif self.reason == "polygon_coordinates_wrong_format":
|
|
1307
|
-
msg += (
|
|
1308
|
-
"Found at least one polygon's coordinates incorrectly formatted. Each "
|
|
1309
|
-
"polygon's coordinates must be a collection of even number of positive floats "
|
|
1310
|
-
"representing the x and y coordinates of each point, in pixels. The following "
|
|
1311
|
-
f"coordinates are invalid: {self.coordinates}"
|
|
1312
|
-
)
|
|
1313
|
-
elif self.reason == "polygon_coordinates_repeated_vertices":
|
|
1314
|
-
msg += (
|
|
1315
|
-
"Found at least one polygon with repeated vertices. "
|
|
1316
|
-
"No polygon can have repeated vertices. "
|
|
1317
|
-
f"The following coordinates are invalid: {self.coordinates}"
|
|
1318
|
-
)
|
|
1319
|
-
elif self.reason == "polygon_coordinates_self_intersecting_vertices":
|
|
1320
|
-
msg += (
|
|
1321
|
-
"Found at least one polygon with self-intersecting vertices. "
|
|
1322
|
-
"Each polygon must not have self-intersecting vertices. "
|
|
1323
|
-
f"The following coordinates are invalid: {self.coordinates}"
|
|
1324
|
-
)
|
|
1325
|
-
return msg
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
class InvalidPolygonCategories(ValidationError, Exception):
|
|
1329
|
-
"""Raised when polygon categories are invalid or missing."""
|
|
1330
|
-
|
|
1331
|
-
def __repr__(self) -> str:
|
|
1332
|
-
"""Return a string representation for debugging and logging."""
|
|
1333
|
-
return "Invalid_Polygon_Categories"
|
|
1334
|
-
|
|
1335
|
-
def __init__(self, reason: str) -> None:
|
|
1336
|
-
"""Initialize the exception with polygon category validation context.
|
|
1337
|
-
|
|
1338
|
-
Args:
|
|
1339
|
-
reason: Specific reason for invalid categories (e.g., "none_category_list",
|
|
1340
|
-
"none_category").
|
|
1341
|
-
"""
|
|
1342
|
-
self._check_valid_reason(reason)
|
|
1343
|
-
self.reason = reason
|
|
1344
|
-
|
|
1345
|
-
@staticmethod
|
|
1346
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1347
|
-
possible_reasons = (
|
|
1348
|
-
"none_category_list",
|
|
1349
|
-
"none_category",
|
|
1350
|
-
)
|
|
1351
|
-
if reason not in possible_reasons:
|
|
1352
|
-
raise ValueError(
|
|
1353
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1354
|
-
f"{', '.join(possible_reasons)}."
|
|
1355
|
-
)
|
|
1356
|
-
|
|
1357
|
-
def error_message(self) -> str:
|
|
1358
|
-
"""Return the error message for this exception."""
|
|
1359
|
-
msg = "Invalid polygon categories found. "
|
|
1360
|
-
if self.reason == "none_category_list":
|
|
1361
|
-
msg += (
|
|
1362
|
-
"Found at least one list of polygon categories with None value. Must send a "
|
|
1363
|
-
"list of categories, one category per polygon."
|
|
1364
|
-
)
|
|
1365
|
-
elif self.reason == "none_category":
|
|
1366
|
-
msg += (
|
|
1367
|
-
"Found at least one category label with None value. Each polygon category "
|
|
1368
|
-
"must be string. Empty strings are allowed"
|
|
1369
|
-
)
|
|
1370
|
-
return msg
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
class InvalidPolygonScores(ValidationError, Exception):
|
|
1374
|
-
"""Raised when polygon confidence scores are invalid or out of bounds."""
|
|
1375
|
-
|
|
1376
|
-
def __repr__(self) -> str:
|
|
1377
|
-
"""Return a string representation for debugging and logging."""
|
|
1378
|
-
return "Invalid_Polygon_Scores"
|
|
1379
|
-
|
|
1380
|
-
def __init__(self, reason: str) -> None:
|
|
1381
|
-
"""Initialize the exception with polygon score validation context.
|
|
1382
|
-
|
|
1383
|
-
Args:
|
|
1384
|
-
reason: Specific reason for invalid scores (e.g., "none_score_list",
|
|
1385
|
-
"scores_out_of_bounds").
|
|
1386
|
-
"""
|
|
1387
|
-
self._check_valid_reason(reason)
|
|
1388
|
-
self.reason = reason
|
|
1389
|
-
|
|
1390
|
-
@staticmethod
|
|
1391
|
-
def _check_valid_reason(reason: str) -> None:
|
|
1392
|
-
possible_reasons = (
|
|
1393
|
-
"none_score_list",
|
|
1394
|
-
"scores_out_of_bounds",
|
|
1395
|
-
)
|
|
1396
|
-
if reason not in possible_reasons:
|
|
1397
|
-
raise ValueError(
|
|
1398
|
-
f"Invalid reason {reason}. Possible reasons are: "
|
|
1399
|
-
f"{', '.join(possible_reasons)}."
|
|
1400
|
-
)
|
|
1401
|
-
|
|
1402
|
-
def error_message(self) -> str:
|
|
1403
|
-
"""Return the error message for this exception."""
|
|
1404
|
-
msg = "Invalid polygon scores found. "
|
|
1405
|
-
if self.reason == "none_score_list":
|
|
1406
|
-
msg += (
|
|
1407
|
-
"Found at least one list of polygon scores with None value. This field is "
|
|
1408
|
-
"optional. If sent, you must send a confidence score per polygon"
|
|
1409
|
-
)
|
|
1410
|
-
elif self.reason == "scores_out_of_bounds":
|
|
1411
|
-
msg += (
|
|
1412
|
-
"Found at least one confidence score out of bounds. "
|
|
1413
|
-
"Confidence scores must be between 0 and 1"
|
|
1414
|
-
)
|
|
1415
|
-
return msg
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
class InvalidNumClassesMultiClassMap(ValidationError):
|
|
1419
|
-
"""Raised when multi-class dictionary contains invalid number of classes."""
|
|
1420
|
-
|
|
1421
|
-
def __repr__(self) -> str:
|
|
1422
|
-
"""Return a string representation for debugging and logging."""
|
|
1423
|
-
return "Invalid_Num_classes_Multi_Class_Map"
|
|
1424
|
-
|
|
1425
|
-
def __init__(
|
|
1426
|
-
self, dict_col_to_list_of_invalid_num_classes: dict[str, list[str]]
|
|
1427
|
-
) -> None:
|
|
1428
|
-
"""Initialize the exception with multi-class number validation context.
|
|
1429
|
-
|
|
1430
|
-
Args:
|
|
1431
|
-
dict_col_to_list_of_invalid_num_classes: Mapping of columns to lists of
|
|
1432
|
-
invalid number of classes found.
|
|
1433
|
-
"""
|
|
1434
|
-
self.invalid_col_num_classes = dict_col_to_list_of_invalid_num_classes
|
|
1435
|
-
|
|
1436
|
-
def error_message(self) -> str:
|
|
1437
|
-
"""Return the error message for this exception."""
|
|
1438
|
-
err_msg = ""
|
|
1439
|
-
for (
|
|
1440
|
-
col,
|
|
1441
|
-
list_invalid_num_classes,
|
|
1442
|
-
) in self.invalid_col_num_classes.items():
|
|
1443
|
-
num_invalid_num_classes = len(list_invalid_num_classes)
|
|
1444
|
-
set_invalid_num_classes = set(
|
|
1445
|
-
list_invalid_num_classes
|
|
1446
|
-
) # to de-duplicate
|
|
1447
|
-
err_msg += (
|
|
1448
|
-
f"Multi-Class dictionary for the following column: {col} had {num_invalid_num_classes} rows "
|
|
1449
|
-
f"containing an invalid number of classes. The dictionary must contain at least 1 class "
|
|
1450
|
-
f"and at most {MAX_NUMBER_OF_MULTI_CLASS_CLASSES} classes. Found rows with the following "
|
|
1451
|
-
f"invalid number of classes: {log_a_list(list(set_invalid_num_classes), 'and')}\n"
|
|
1452
|
-
)
|
|
1453
|
-
return err_msg
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
class InvalidMultiClassClassNameLength(ValidationError):
|
|
1457
|
-
"""Raised when multi-class class names exceed maximum length."""
|
|
1458
|
-
|
|
1459
|
-
def __repr__(self) -> str:
|
|
1460
|
-
"""Return a string representation for debugging and logging."""
|
|
1461
|
-
return "Invalid_Multi_Class_Class_Name_Length"
|
|
1462
|
-
|
|
1463
|
-
def __init__(self, invalid_col_class_name: dict[str, set]) -> None:
|
|
1464
|
-
"""Initialize the exception with multi-class name length validation context.
|
|
1465
|
-
|
|
1466
|
-
Args:
|
|
1467
|
-
invalid_col_class_name: Mapping of columns to sets of invalid class names.
|
|
1468
|
-
"""
|
|
1469
|
-
self.invalid_col_class_name = invalid_col_class_name
|
|
1470
|
-
|
|
1471
|
-
def error_message(self) -> str:
|
|
1472
|
-
"""Return the error message for this exception."""
|
|
1473
|
-
err_msg = ""
|
|
1474
|
-
for col, class_names in self.invalid_col_class_name.items():
|
|
1475
|
-
# limit to 10
|
|
1476
|
-
class_names = (
|
|
1477
|
-
list(class_names)[:10]
|
|
1478
|
-
if len(class_names) > 10
|
|
1479
|
-
else list(class_names)
|
|
1480
|
-
)
|
|
1481
|
-
err_msg += (
|
|
1482
|
-
f"Found some invalid class names: {log_a_list(class_names, 'and')} "
|
|
1483
|
-
f"in the {col} column. Class names must have at least one character "
|
|
1484
|
-
f"and less than {MAX_MULTI_CLASS_NAME_LENGTH}.\n"
|
|
1485
|
-
)
|
|
1486
|
-
return err_msg
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
class InvalidMultiClassPredScoreValue(ValidationError):
|
|
1490
|
-
"""Raised when multi-class prediction scores are outside valid range."""
|
|
1491
|
-
|
|
1492
|
-
def __repr__(self) -> str:
|
|
1493
|
-
"""Return a string representation for debugging and logging."""
|
|
1494
|
-
return "Invalid_Multi_Class_Pred_Score_Value"
|
|
1495
|
-
|
|
1496
|
-
def __init__(self, invalid_col_class_scores: dict[str, set]) -> None:
|
|
1497
|
-
"""Initialize the exception with multi-class prediction score validation context.
|
|
1498
|
-
|
|
1499
|
-
Args:
|
|
1500
|
-
invalid_col_class_scores: Mapping of columns to sets of invalid scores.
|
|
1501
|
-
"""
|
|
1502
|
-
self.invalid_col_class_scores = invalid_col_class_scores
|
|
1503
|
-
|
|
1504
|
-
def error_message(self) -> str:
|
|
1505
|
-
"""Return the error message for this exception."""
|
|
1506
|
-
err_msg = ""
|
|
1507
|
-
for col, scores in self.invalid_col_class_scores.items():
|
|
1508
|
-
# limit to 10
|
|
1509
|
-
scores = list(scores)[:10] if len(scores) > 10 else list(scores)
|
|
1510
|
-
err_msg += (
|
|
1511
|
-
f"Found some invalid scores: {log_a_list(scores, 'and')} in the {col} column that was "
|
|
1512
|
-
"invalid. All scores (values in dictionary) must be between 0 and 1, inclusive. \n"
|
|
1513
|
-
)
|
|
1514
|
-
return err_msg
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
class InvalidMultiClassActScoreValue(ValidationError):
|
|
1518
|
-
"""Raised when multi-class actual scores are not 0 or 1."""
|
|
1519
|
-
|
|
1520
|
-
def __repr__(self) -> str:
|
|
1521
|
-
"""Return a string representation for debugging and logging."""
|
|
1522
|
-
return "Invalid_Multi_Class_Act_Score_Value"
|
|
1523
|
-
|
|
1524
|
-
def __init__(self, name: str) -> None:
|
|
1525
|
-
"""Initialize the exception with multi-class actual score validation context.
|
|
1526
|
-
|
|
1527
|
-
Args:
|
|
1528
|
-
name: Name of the column with invalid actual scores.
|
|
1529
|
-
"""
|
|
1530
|
-
self.name = name
|
|
1531
|
-
|
|
1532
|
-
def error_message(self) -> str:
|
|
1533
|
-
"""Return the error message for this exception."""
|
|
1534
|
-
return (
|
|
1535
|
-
f"Found at least one score in the '{self.name}' column that was invalid. "
|
|
1536
|
-
f"All scores (values) must be either 0 or 1."
|
|
1537
|
-
)
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
class InvalidMultiClassThresholdClasses(ValidationError):
|
|
1541
|
-
"""Raised when prediction and threshold score dictionaries have mismatched classes."""
|
|
1542
|
-
|
|
1543
|
-
def __repr__(self) -> str:
|
|
1544
|
-
"""Return a string representation for debugging and logging."""
|
|
1545
|
-
return "Invalid_Multi_Class_Threshold_Classes"
|
|
1546
|
-
|
|
1547
|
-
def __init__(
|
|
1548
|
-
self, name: str, prediction_class_set: set, threshold_class_set: set
|
|
1549
|
-
) -> None:
|
|
1550
|
-
"""Initialize the exception with multi-class threshold validation context.
|
|
1551
|
-
|
|
1552
|
-
Args:
|
|
1553
|
-
name: Name of the field being validated.
|
|
1554
|
-
prediction_class_set: Set of classes in prediction scores dictionary.
|
|
1555
|
-
threshold_class_set: Set of classes in threshold scores dictionary.
|
|
1556
|
-
"""
|
|
1557
|
-
self.name = name
|
|
1558
|
-
self.prediction_class_set = prediction_class_set
|
|
1559
|
-
self.threshold_class_set = threshold_class_set
|
|
1560
|
-
|
|
1561
|
-
def error_message(self) -> str:
|
|
1562
|
-
"""Return the error message for this exception."""
|
|
1563
|
-
return (
|
|
1564
|
-
"Multi-Class Prediction Scores and Threshold Scores Dictionaries must contain the same "
|
|
1565
|
-
f"classes. The following classes of the Prediction Scores Dictionary are not in the Threshold "
|
|
1566
|
-
f"Scores Dictionary: {self.prediction_class_set.difference(self.threshold_class_set)}"
|
|
1567
|
-
"\nThe following classes of the Threshold Scores Dictionary are not in the Prediction Scores "
|
|
1568
|
-
f"Dictionary: {self.threshold_class_set.difference(self.prediction_class_set)}\n"
|
|
1569
|
-
)
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
class InvalidAdditionalHeaders(ValidationError):
|
|
1573
|
-
"""Raised when additional headers use reserved header names."""
|
|
1574
|
-
|
|
1575
|
-
def __repr__(self) -> str:
|
|
1576
|
-
"""Return a string representation for debugging and logging."""
|
|
1577
|
-
return "Invalid_Additional_Headers"
|
|
1578
|
-
|
|
1579
|
-
def __init__(self, invalid_headers: Iterable) -> None:
|
|
1580
|
-
"""Initialize the exception with invalid headers context.
|
|
1581
|
-
|
|
1582
|
-
Args:
|
|
1583
|
-
invalid_headers: Headers that use reserved names.
|
|
1584
|
-
"""
|
|
1585
|
-
self.invalid_header_names = invalid_headers
|
|
1586
|
-
|
|
1587
|
-
def error_message(self) -> str:
|
|
1588
|
-
"""Return the error message for this exception."""
|
|
1589
|
-
return (
|
|
1590
|
-
"Found invalid additional header, cannot use reserved headers named: "
|
|
1591
|
-
f"{', '.join(map(str, self.invalid_header_names))}."
|
|
1592
|
-
)
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
class InvalidRecord(ValidationError):
|
|
1596
|
-
"""Raised when records contain invalid or all-null column sets."""
|
|
1597
|
-
|
|
1598
|
-
def __repr__(self) -> str:
|
|
1599
|
-
"""Return a string representation for debugging and logging."""
|
|
1600
|
-
return "Invalid_Record"
|
|
1601
|
-
|
|
1602
|
-
def __init__(self, columns: list[str], indexes: list[int]) -> None:
|
|
1603
|
-
"""Initialize the exception with invalid record context.
|
|
1604
|
-
|
|
1605
|
-
Args:
|
|
1606
|
-
columns: Columns that form an invalid all-null set.
|
|
1607
|
-
indexes: Row indexes containing the invalid records.
|
|
1608
|
-
"""
|
|
1609
|
-
self.columns = columns
|
|
1610
|
-
self.indexes = indexes
|
|
1611
|
-
|
|
1612
|
-
def error_message(self) -> str:
|
|
1613
|
-
"""Return the error message for this exception."""
|
|
1614
|
-
return (
|
|
1615
|
-
f"Invalid column set full of null values in one or more rows.\n"
|
|
1616
|
-
f"\nProblematic Column Set:\n{log_a_list(self.columns, 'and')}\n"
|
|
1617
|
-
f"\nProblematic Rows:\n{log_a_list(self.indexes, join_word='and')}\n"
|
|
1618
|
-
"\nThis violates one of the following requirements:\n"
|
|
1619
|
-
" - If training environment: Prediction or actual columns cannot be all null.\n"
|
|
1620
|
-
" - If production environment: Prediction and actual columns cannot be all null.\n"
|
|
1621
|
-
" - If you are sending SHAP values, make sure not all your SHAP values are null "
|
|
1622
|
-
"in any given row.\n"
|
|
1623
|
-
)
|