# Copyright 2025 Collate
# Licensed under the Collate Community License, Version 1.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# https://github.com/open-metadata/OpenMetadata/blob/main/ingestion/LICENSE
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
OpenMetadata high-level API Custom Properties Test
"""
from typing import Dict
from unittest import TestCase
from metadata.generated.schema.api.data.createCustomProperty import (
CreateCustomPropertyRequest,
)
from metadata.generated.schema.api.data.createDatabase import CreateDatabaseRequest
from metadata.generated.schema.api.data.createDatabaseSchema import (
CreateDatabaseSchemaRequest,
)
from metadata.generated.schema.api.data.createTable import CreateTableRequest
from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest,
)
from metadata.generated.schema.api.teams.createUser import CreateUserRequest
from metadata.generated.schema.entity.data.databaseSchema import DatabaseSchema
from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection,
)
from metadata.generated.schema.entity.services.connections.metadata.openMetadataConnection import (
OpenMetadataConnection,
)
from metadata.generated.schema.entity.services.databaseService import (
DatabaseConnection,
DatabaseService,
DatabaseServiceType,
)
from metadata.generated.schema.entity.teams.user import User
from metadata.generated.schema.security.client.openMetadataJWTClientConfig import (
OpenMetadataJWTClientConfig,
)
from metadata.generated.schema.type.basic import EntityExtension
from metadata.generated.schema.type.customProperties.enumConfig import EnumConfig
from metadata.generated.schema.type.customProperty import (
CustomPropertyConfig,
EntityTypes,
Format,
)
from metadata.generated.schema.type.entityReference import EntityReference
from metadata.ingestion.models.custom_properties import (
CustomPropertyDataTypes,
OMetaCustomProperties,
)
from metadata.ingestion.ometa.ometa_api import OpenMetadata
from metadata.utils.constants import ENTITY_REFERENCE_TYPE_MAP
EXPECTED_CUSTOM_PROPERTIES = [
{
"name": "DataEngineers",
"description": "Data Engineers of a table",
"propertyType": {
"name": "entityReferenceList",
},
"customPropertyConfig": {"config": ["user"]},
},
{
"name": "DataQuality",
"description": "Quality Details of a Table",
"propertyType": {
"name": "markdown",
},
},
{
"name": "Department",
"description": "Department of a table",
"propertyType": {
"type": "type",
"name": "enum",
},
"customPropertyConfig": {
"config": {"values": ["D1", "D2", "D3"], "multiSelect": True}
},
},
{
"name": "Rating",
"description": "Rating of a table",
"propertyType": {"name": "enum"},
"customPropertyConfig": {
"config": {"values": ["Average", "Bad", "Good"], "multiSelect": False},
},
},
{
"name": "TableSize",
"description": "Size of the Table",
"propertyType": {"name": "string"},
},
]
class OMetaCustomAttributeTest(TestCase):
"""
Run this integration test with the local API available
Install the ingestion package before running the tests
"""
service_entity_id = None
server_config = OpenMetadataConnection(
hostPort="http://localhost:8585/api",
authProvider="openmetadata",
securityConfig=OpenMetadataJWTClientConfig(
jwtToken="eyJraWQiOiJHYjM4OWEtOWY3Ni1nZGpzLWE5MmotMDI0MmJrOTQzNTYiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlzQm90IjpmYWxzZSwiaXNzIjoib3Blbi1tZXRhZGF0YS5vcmciLCJpYXQiOjE2NjM5Mzg0NjIsImVtYWlsIjoiYWRtaW5Ab3Blbm1ldGFkYXRhLm9yZyJ9.tS8um_5DKu7HgzGBzS1VTA5uUjKWOCU0B_j08WXBiEC0mr0zNREkqVfwFDD-d24HlNEbrqioLsBuFRiwIWKc1m_ZlVQbG7P36RUxhuv2vbSp80FKyNM-Tj93FDzq91jsyNmsQhyNv_fNr3TXfzzSPjHt8Go0FMMP66weoKMgW2PbXlhVKwEuXUHyakLLzewm9UMeQaEiRzhiTMU3UkLXcKbYEJJvfNFcLwSl9W8JCO_l0Yj3ud-qt_nQYEZwqW6u5nfdQllN133iikV4fM5QZsMCnm8Rq1mvLR0y9bmJiD7fwM1tmJ791TUWqmKaTnP49U493VanKpUAfzIiOiIbhg"
),
)
metadata = OpenMetadata(server_config)
assert metadata.health_check()
service = CreateDatabaseServiceRequest(
name="test-service-custom-properties",
serviceType=DatabaseServiceType.Mysql,
connection=DatabaseConnection(
config=MysqlConnection(
username="username",
authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234",
)
),
)
service_type = "databaseService"
def create_table(self, name: str, extensions: Dict) -> Table:
create = CreateTableRequest(
name=name,
databaseSchema=self.create_schema_entity.fullyQualifiedName,
columns=[Column(name="id", dataType=DataType.BIGINT)],
extension=EntityExtension(root=extensions),
)
return self.metadata.create_or_update(create)
@classmethod
def setUpClass(cls) -> None:
"""
Prepare ingredients
"""
cls.service_entity = cls.metadata.create_or_update(data=cls.service)
create_db = CreateDatabaseRequest(
name="test-db",
service=cls.service_entity.fullyQualifiedName,
)
cls.create_db_entity = cls.metadata.create_or_update(data=create_db)
create_schema = CreateDatabaseSchemaRequest(
name="test-schema",
database=cls.create_db_entity.fullyQualifiedName,
)
cls.create_schema_entity = cls.metadata.create_or_update(data=create_schema)
user_one: User = cls.metadata.create_or_update(
data=CreateUserRequest(
name="custom-prop-user-one", email="custom-prop-user-one@user.com"
),
)
user_two: User = cls.metadata.create_or_update(
data=CreateUserRequest(
name="custom-prop-user-two", email="custom-prop-user-two@user.com"
),
)
cls.user_one_ref = EntityReference(
id=user_one.id,
name="custom-prop-user-one",
type="user",
fullyQualifiedName=user_one.fullyQualifiedName.root,
)
cls.user_two = EntityReference(
id=user_two.id,
name="custom-prop-user-two",
type="user",
fullyQualifiedName=user_two.fullyQualifiedName.root,
)
@classmethod
def tearDownClass(cls) -> None:
"""
Clean up
"""
service_id = str(
cls.metadata.get_by_name(
entity=DatabaseService, fqn="test-service-custom-properties"
).id.root
)
cls.metadata.delete(
entity=DatabaseService,
entity_id=service_id,
recursive=True,
hard_delete=True,
)
def create_custom_property(self):
"""
Test to create the custom property
"""
# Create the table size property
ometa_custom_property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="TableSize",
description="Size of the Table",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.STRING
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
# Create the DataQuality property for a table
ometa_custom_property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="DataQuality",
description="Quality Details of a Table",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.MARKDOWN
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
# Create the SchemaCost property for database schema
ometa_custom_property_request = OMetaCustomProperties(
entity_type=DatabaseSchema,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="SchemaAge",
description="Age in years of a Schema",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.INTEGER
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
# Create single select enum custom property for a table
ometa_custom_property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="Rating",
description="Rating of a table",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.ENUM
),
customPropertyConfig=CustomPropertyConfig(
config=EnumConfig(
multiSelect=False, values=["Good", "Average", "Bad"]
)
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
# Create multi select enum custom property for a table
ometa_custom_property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="Department",
description="Department of a table",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.ENUM
),
customPropertyConfig=CustomPropertyConfig(
config=EnumConfig(multiSelect=True, values=["D1", "D2", "D3"])
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
# Create entity reference list custom property for a table
ometa_custom_property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="DataEngineers",
description="Data Engineers of a table",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.ENTITY_REFERENCE_LIST
),
customPropertyConfig=CustomPropertyConfig(
config=EntityTypes(root=[ENTITY_REFERENCE_TYPE_MAP[User.__name__]])
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=ometa_custom_property_request
)
def test_get_custom_property(self):
"""
Test getting the custom properties for an entity
"""
# create the custom properties
self.create_custom_property()
custom_properties = self.metadata.get_entity_custom_properties(
entity_type=Table
)
actual_custom_properties = []
for expected_custom_property in EXPECTED_CUSTOM_PROPERTIES:
for custom_property in custom_properties:
if expected_custom_property["name"] == custom_property["name"]:
actual_custom_properties.append(custom_property)
self.assertEqual(
custom_property["name"], expected_custom_property["name"]
)
self.assertEqual(
custom_property["description"],
expected_custom_property["description"],
)
self.assertEqual(
custom_property.get("customPropertyConfig"),
expected_custom_property.get("customPropertyConfig"),
)
self.assertEqual(
custom_property["propertyType"]["name"],
expected_custom_property["propertyType"]["name"],
)
self.assertEqual(len(actual_custom_properties), len(EXPECTED_CUSTOM_PROPERTIES))
def test_add_custom_property_table(self):
"""
Test to add the extension/custom property to the table
"""
# create the custom properties
self.create_custom_property()
extensions = {
"DataQuality": '
Last evaluation: 07/24/2023
Interval: 30 days
Next run: 08/23/2023, 10:44:21
Measurement unit: percent [%]
Metric | Target | Latest result |
---|
Completeness | 90% | 93% |
Integrity | 90% | 100% |
Timeliness | 90% | 56% |
Uniqueness | 90% | 100% |
Validity | 90% | 100% |
Overall score of the table is: 89%
',
"TableSize": "250 MB",
"Rating": ["Good"],
"Department": ["D1", "D2"],
"DataEngineers": [self.user_one_ref, self.user_two],
}
self.create_table(name="test_custom_properties", extensions=extensions)
res = self.metadata.get_by_name(
entity=Table,
fqn="test-service-custom-properties.test-db.test-schema.test_custom_properties",
fields=["*"],
)
self.assertEqual(res.extension.root["DataQuality"], extensions["DataQuality"])
self.assertEqual(res.extension.root["TableSize"], extensions["TableSize"])
self.assertEqual(res.extension.root["Rating"], extensions["Rating"])
self.assertEqual(res.extension.root["Department"], extensions["Department"])
self.assertEqual(
res.extension.root["DataEngineers"][0]["id"],
str(extensions["DataEngineers"][0].id.root),
)
self.assertEqual(
res.extension.root["DataEngineers"][1]["id"],
str(extensions["DataEngineers"][1].id.root),
)
def test_add_custom_property_schema(self):
"""
Test to add the extension/custom property to the schema
"""
# create the custom properties
self.create_custom_property()
extensions = {"SchemaAge": 3}
create_schema = CreateDatabaseSchemaRequest(
name="test-schema-custom-property",
database=self.create_db_entity.fullyQualifiedName,
extension=EntityExtension(root=extensions),
)
self.metadata.create_or_update(data=create_schema)
res = self.metadata.get_by_name(
entity=DatabaseSchema,
fqn="test-service-custom-properties.test-db.test-schema-custom-property",
fields=["*"],
)
self.assertEqual(res.extension.root["SchemaAge"], extensions["SchemaAge"])
def test_custom_property_data_types_enum_values(self):
"""
Test that CustomPropertyDataTypes enum has correct values, especially for date/time types
"""
# Test that the enum values are correct
self.assertEqual(CustomPropertyDataTypes.STRING.value, "string")
self.assertEqual(CustomPropertyDataTypes.INTEGER.value, "integer")
self.assertEqual(CustomPropertyDataTypes.MARKDOWN.value, "markdown")
self.assertEqual(CustomPropertyDataTypes.DATE.value, "date-cp")
self.assertEqual(CustomPropertyDataTypes.DATETIME.value, "dateTime-cp")
self.assertEqual(CustomPropertyDataTypes.TIME.value, "time-cp")
self.assertEqual(CustomPropertyDataTypes.DURATION.value, "duration")
self.assertEqual(CustomPropertyDataTypes.EMAIL.value, "email")
self.assertEqual(CustomPropertyDataTypes.NUMBER.value, "number")
self.assertEqual(CustomPropertyDataTypes.SQLQUERY.value, "sqlQuery")
self.assertEqual(CustomPropertyDataTypes.TIMEINTERVAL.value, "timeInterval")
self.assertEqual(CustomPropertyDataTypes.TIMESTAMP.value, "timestamp")
self.assertEqual(CustomPropertyDataTypes.ENUM.value, "enum")
self.assertEqual(
CustomPropertyDataTypes.ENTITY_REFERENCE.value, "entityReference"
)
self.assertEqual(
CustomPropertyDataTypes.ENTITY_REFERENCE_LIST.value, "entityReferenceList"
)
def test_date_time_custom_properties(self):
"""
Test creating custom properties with date/time types using the updated enum values
"""
# Test DATE custom property
date_property = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="CreationDate",
description="Date when the table was created",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.DATE
),
customPropertyConfig=CustomPropertyConfig(config=Format("yyyy-MM-dd")),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=date_property
)
# Test DATETIME custom property
datetime_property = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="LastModifiedDateTime",
description="Date and time when the table was last modified",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.DATETIME
),
customPropertyConfig=CustomPropertyConfig(
config=Format("yyyy-MM-dd'T'HH:mm:ss'Z'")
),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=datetime_property
)
# Test TIME custom property
time_property = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=CreateCustomPropertyRequest(
name="DailyBackupTime",
description="Time when daily backup occurs",
propertyType=self.metadata.get_property_type_ref(
CustomPropertyDataTypes.TIME
),
customPropertyConfig=CustomPropertyConfig(config=Format("HH:mm:ss")),
),
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=time_property
)
# Verify the properties were created
custom_properties = self.metadata.get_entity_custom_properties(
entity_type=Table
)
date_prop = next(
(cp for cp in custom_properties if cp["name"] == "CreationDate"), None
)
datetime_prop = next(
(cp for cp in custom_properties if cp["name"] == "LastModifiedDateTime"),
None,
)
time_prop = next(
(cp for cp in custom_properties if cp["name"] == "DailyBackupTime"), None
)
self.assertIsNotNone(date_prop)
self.assertIsNotNone(datetime_prop)
self.assertIsNotNone(time_prop)
# Verify the property types are correct
self.assertEqual(date_prop["propertyType"]["name"], "date-cp")
self.assertEqual(datetime_prop["propertyType"]["name"], "dateTime-cp")
self.assertEqual(time_prop["propertyType"]["name"], "time-cp")
def test_all_custom_property_data_types(self):
"""
Test creating custom properties for all available data types
"""
test_cases = [
(
CustomPropertyDataTypes.STRING,
"TestString",
"String test property",
None,
),
(
CustomPropertyDataTypes.INTEGER,
"TestInteger",
"Integer test property",
None,
),
(
CustomPropertyDataTypes.MARKDOWN,
"TestMarkdown",
"Markdown test property",
None,
),
(
CustomPropertyDataTypes.DATE,
"TestDate",
"Date test property",
"yyyy-MM-dd",
),
(
CustomPropertyDataTypes.DATETIME,
"TestDateTime",
"DateTime test property",
"yyyy-MM-dd HH:mm:ss",
),
(
CustomPropertyDataTypes.TIME,
"TestTime",
"Time test property",
"HH:mm:ss",
),
(
CustomPropertyDataTypes.DURATION,
"TestDuration",
"Duration test property",
None,
),
(CustomPropertyDataTypes.EMAIL, "TestEmail", "Email test property", None),
(
CustomPropertyDataTypes.NUMBER,
"TestNumber",
"Number test property",
None,
),
(
CustomPropertyDataTypes.SQLQUERY,
"TestSqlQuery",
"SQL Query test property",
None,
),
(
CustomPropertyDataTypes.TIMEINTERVAL,
"TestTimeInterval",
"Time Interval test property",
None,
),
(
CustomPropertyDataTypes.TIMESTAMP,
"TestTimestamp",
"Timestamp test property",
None,
),
]
for data_type, name, description, custom_property_config in test_cases:
with self.subTest(data_type=data_type):
create_custom_property_request = CreateCustomPropertyRequest(
name=name,
description=description,
propertyType=self.metadata.get_property_type_ref(data_type),
)
# For date/time custom properties, we need to add the format to the custom property config
if custom_property_config:
create_custom_property_request.customPropertyConfig = (
CustomPropertyConfig(config=Format(custom_property_config))
)
property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=create_custom_property_request,
)
# This should not raise an exception
result = self.metadata.create_or_update_custom_property(
ometa_custom_property=property_request
)
self.assertIsNotNone(result)
# Verify all properties were created
custom_properties = self.metadata.get_entity_custom_properties(
entity_type=Table
)
created_properties = {cp["name"]: cp for cp in custom_properties}
for data_type, name, description, _ in test_cases:
with self.subTest(data_type=data_type, name=name):
self.assertIn(name, created_properties)
prop = created_properties[name]
self.assertEqual(prop["description"], description)
self.assertEqual(prop["propertyType"]["name"], data_type.value)
def test_custom_property_with_date_time_values(self):
"""
Test adding actual date/time values to custom properties
"""
# Create date/time custom properties
self.test_date_time_custom_properties()
# Test data for date/time properties
extensions = {
"CreationDate": "2023-12-01",
"LastModifiedDateTime": "2023-12-01T10:30:00Z",
"DailyBackupTime": "02:00:00",
}
table = self.create_table(
name="test_datetime_properties", extensions=extensions
)
# Verify the table was created with the date/time extensions
res = self.metadata.get_by_name(
entity=Table,
fqn="test-service-custom-properties.test-db.test-schema.test_datetime_properties",
fields=["*"],
)
self.assertEqual(res.extension.root["CreationDate"], extensions["CreationDate"])
self.assertEqual(
res.extension.root["LastModifiedDateTime"],
extensions["LastModifiedDateTime"],
)
self.assertEqual(
res.extension.root["DailyBackupTime"], extensions["DailyBackupTime"]
)
def test_custom_property_enum_backwards_compatibility(self):
"""
Test that the enum values work correctly with property type references
"""
# Test that get_property_type_ref works with the new enum values
date_type_ref = self.metadata.get_property_type_ref(
CustomPropertyDataTypes.DATE
)
datetime_type_ref = self.metadata.get_property_type_ref(
CustomPropertyDataTypes.DATETIME
)
time_type_ref = self.metadata.get_property_type_ref(
CustomPropertyDataTypes.TIME
)
# These should not be None and should have the correct structure
self.assertIsNotNone(date_type_ref)
self.assertIsNotNone(datetime_type_ref)
self.assertIsNotNone(time_type_ref)
# Verify the type references have the correct structure (EntityReference with id and type)
self.assertIsNotNone(date_type_ref.root.id)
self.assertEqual(date_type_ref.root.type, "type")
self.assertIsNotNone(datetime_type_ref.root.id)
self.assertEqual(datetime_type_ref.root.type, "type")
self.assertIsNotNone(time_type_ref.root.id)
self.assertEqual(time_type_ref.root.type, "type")
def test_custom_property_data_types_completeness(self):
"""
Test that all CustomPropertyDataTypes enum members are properly defined
"""
# Test that all enum members have string values
for data_type in CustomPropertyDataTypes:
self.assertIsInstance(data_type.value, str)
self.assertGreater(len(data_type.value), 0)
# Test specific enum members that were changed
date_time_types = [
CustomPropertyDataTypes.DATE,
CustomPropertyDataTypes.DATETIME,
CustomPropertyDataTypes.TIME,
]
for data_type in date_time_types:
# These should all have the -cp suffix
self.assertTrue(data_type.value.endswith("-cp"))
# Test that other types don't have the -cp suffix
non_cp_types = [
CustomPropertyDataTypes.STRING,
CustomPropertyDataTypes.INTEGER,
CustomPropertyDataTypes.MARKDOWN,
CustomPropertyDataTypes.DURATION,
CustomPropertyDataTypes.EMAIL,
CustomPropertyDataTypes.NUMBER,
CustomPropertyDataTypes.SQLQUERY,
CustomPropertyDataTypes.TIMEINTERVAL,
CustomPropertyDataTypes.TIMESTAMP,
CustomPropertyDataTypes.ENUM,
CustomPropertyDataTypes.ENTITY_REFERENCE,
CustomPropertyDataTypes.ENTITY_REFERENCE_LIST,
]
for data_type in non_cp_types:
self.assertFalse(data_type.value.endswith("-cp"))
def test_custom_property_mixed_data_types(self):
"""
Test creating a table with mixed custom property data types
"""
# Create various custom properties
properties_to_create = [
(CustomPropertyDataTypes.STRING, "Description", "Table description"),
(CustomPropertyDataTypes.INTEGER, "RowCount", "Number of rows"),
(CustomPropertyDataTypes.DATE, "CreatedDate", "Creation date"),
(CustomPropertyDataTypes.DATETIME, "LastUpdated", "Last update timestamp"),
(CustomPropertyDataTypes.TIME, "BackupTime", "Backup time"),
(CustomPropertyDataTypes.EMAIL, "Owner", "Owner email"),
(CustomPropertyDataTypes.NUMBER, "SizeGB", "Size in GB"),
]
for data_type, name, description in properties_to_create:
create_request = CreateCustomPropertyRequest(
name=name,
description=description,
propertyType=self.metadata.get_property_type_ref(data_type),
)
# Add format configuration for date/time properties
if data_type in [
CustomPropertyDataTypes.DATE,
CustomPropertyDataTypes.DATETIME,
CustomPropertyDataTypes.TIME,
]:
if data_type == CustomPropertyDataTypes.DATE:
create_request.customPropertyConfig = CustomPropertyConfig(
config=Format("yyyy-MM-dd")
)
elif data_type == CustomPropertyDataTypes.DATETIME:
create_request.customPropertyConfig = CustomPropertyConfig(
config=Format("yyyy-MM-dd'T'HH:mm:ss'Z'")
)
elif data_type == CustomPropertyDataTypes.TIME:
create_request.customPropertyConfig = CustomPropertyConfig(
config=Format("HH:mm:ss")
)
property_request = OMetaCustomProperties(
entity_type=Table,
createCustomPropertyRequest=create_request,
)
self.metadata.create_or_update_custom_property(
ometa_custom_property=property_request
)
# Create a table with all these properties
extensions = {
"Description": "This is a test table",
"RowCount": 1000,
"CreatedDate": "2023-01-01",
"LastUpdated": "2023-12-01T15:30:00Z",
"BackupTime": "03:00:00",
"Owner": "test@example.com",
"SizeGB": 2.5,
}
table = self.create_table(name="test_mixed_types", extensions=extensions)
# Verify the table was created with all extensions
res = self.metadata.get_by_name(
entity=Table,
fqn="test-service-custom-properties.test-db.test-schema.test_mixed_types",
fields=["*"],
)
for key, expected_value in extensions.items():
self.assertEqual(res.extension.root[key], expected_value)
def test_custom_property_type_ref_error_handling(self):
"""
Test error handling when using invalid custom property types
"""
# Test that valid enum values work
for data_type in CustomPropertyDataTypes:
type_ref = self.metadata.get_property_type_ref(data_type)
self.assertIsNotNone(type_ref)
# Verify the type reference has the correct structure
self.assertIsNotNone(type_ref.root.id)
self.assertEqual(type_ref.root.type, "type")