Hi folks,
I am looking for python script that extract all domains where
code <> description from SDE(oracle) database. any sample code that I could reuse is greatly appreciated.
Ram
The List Domains function is what you're looking for, this will work on any EGDB. The sample code on that page should get you started.
Something like this
egdb = r"GDB.sde"
badDomains = []
for dom in arcpy.da.ListDomains(egdb):
if dom.domainType == "Range":
continue
for key in dom.codedValues:
if key!= dom.codedValues[key]:
badDomains.append(dom.name)
print("done")
print(badDomains)
NOTE: In your version, if a domain has multiple non-matching values, it is added multiple times.
You can also do this in a dictionary comprehension:
def bad_domain(dataset: str):
from arcpy.da import ListDomains
return {
d.name: d
for d in ListDomains(dataset)
if d.domainType == 'CodedValue'
and not all(
value_key == value_description
for value_key, value_description in d.codedValues.items()
)
}
I usually like to unroll these types of filters into multiple functions so it's clear exactly what checks are being made:
from typing import Any
from arcpy.da import Domain
def is_bad_values(val: dict[Any, str]):
any(k != v for k, v in val.items())
def is_bad_domain(d: Domain):
return d.domainType == 'CodedValue' and is_bad_values(d.codedValues)
def bad_domains(dataset: str):
from arcpy.da import ListDomains
return {d.name: d for d in ListDomains(dataset) if is_bad_domain(d)}
If you want to get REALLY re-usable, you can use a registration pattern:
from collections.abc import Callable
from functools import wraps
from typing import Any
from arcpy.da import Domain
type DomainValidator = Callable[[Domain], bool]
Validators: list[DomainValidator] = []
VALID = True
INVALID = False
def register_validator(func: DomainValidator):
Validators.append(func)
@wraps
def _wrapper(*args: Any, **kwargs: Any):
return func(*args, **kwargs)
return _wrapper
@register_validator
def domain_value_check(d: Domain):
if d.domainType == 'CodedValue' :
if any(k != v for k, v in d.codedValues.items()):
return INVALID
return VALID
@register_validator
def domain_range_check(d: Domain):
if d.domainType == 'Range':
min, max = d.range
if not isinstance(min, (int, float)):
return INVALID
if not isinstance(max, (int, float)):
return INVALID
if min < 0 or max > 100:
return INVALID
return VALID
def bad_domains(dataset: str, validators: list[DomainValidator]=Validators):
from arcpy.da import ListDomains
return {
d.name: d
for d in ListDomains(dataset)
if any(validator(d) is INVALID for validator in validators)
}
Now you can just add and remove validations as you please.