Quick & Dirty Arcpy: Verify a Coded Value Domain Code

I’ve been working on a few different data import routines and one of the things I recently built was the ability to verify that a potential Code to be entered into a field with a Coded Value Domain is valid.

The logic of the code is pretty straight-forward. Get a field’s domain and check that a potential value is one of the code values. The biggest “trick” in this code is that arcpy.da.ListDomains, which locates a field’s domain, takes a geodatabase (or Enterprise geodatabase connection file) as its only parameter. The documentation says it takes a workspace, but it does not like a feature dataset, which a feature class might be in.

A couple caveats about the code. It only returns True if a field exists, has a coded value domain, and the value tested is one of the (case-sensitive) valid codes. While I have an ArcToolbox tool to call it for illustration purposes, I’m only calling it from code so I wanted tight requirements.

Anyhow, here is the code or download it from GitHub.

import arcpy

inFeatureClass = sys.argv[1]
inField = sys.argv[2]
inValue = sys.argv[3]

# getFeatureClassParentWorkspace: This script gets the geodatabase for a
# feature class. The trick here is that feature classes can be within a
# feature dataset so you need to account for two possible levels in the
# directory structure.
def getFeatureClassParentWorkspace(inFeatureClass):
    describeFC = arcpy.Describe(inFeatureClass)
    if (describeFC.dataType == 'FeatureClass') or (describeFC.dataType == 'Table'):
        workspace1 = describeFC.path
        describeWorkspace1 = arcpy.Describe(workspace1)
        if (describeWorkspace1.dataType == 'FeatureDataset'):
            return describeWorkspace1.path
        return workspace1

    return None

# Find a field within a feature class
def getField(inFeatureClass, inFieldName):
  fieldList = arcpy.ListFields(inFeatureClass)
  for iField in fieldList:
    if iField.name.lower() == inFieldName.lower():
      return iField
  return None

#Get a field's domain
def getDomain(inFeatureClass, inField):
    theField = getField(inFeatureClass,inField)
    if (theField <> None):
        searchDomainName = theField.domain
        if (searchDomainName <> ""):
            for iDomain in arcpy.da.ListDomains(getFeatureClassParentWorkspace(inFeatureClass)):
                if iDomain.name == searchDomainName:
                    return iDomain
    return None

#Get the domain.
def validDomainValue(inFeatureClass,inField,inValue):
    theDomain = getDomain(inFeatureClass,inField)

    if not (theDomain is None):
        if (theDomain.domainType == "CodedValue"):
            if theDomain.codedValues.has_key(inValue):
                return True
    return False

if (validDomainValue(inFeatureClass,inField,inValue)):
    arcpy.AddMessage("Value ({0}) is valid for field [{1}].".format(inValue,inField))
    arcpy.AddError("ERROR: Value ({0}) is invalid for field [{1}].".format(inValue,inField))

One thought on “Quick & Dirty Arcpy: Verify a Coded Value Domain Code

  1. Nice Post and useful!
    I hope you don’t mind, but I like to make a couple suggestions:

    1. I like to avoid using Descibe whenever possible to help improve performance:

    Perhaps a function like this to get the workspace from a table or feature class:

    def get_workspace(in_feature_class):
        workspace = os.path.dirname(in_feature_class)
        if [any(ext) for ext in ('.sde', '.gdb', '.mdb') if ext in os.path.splitext(workspace)]:
            return workspace
            return os.path.dirname(workspace)

    2. You can also do this to shorten the logic and verify a domain value. Plus the “has_key” method is now deprecated and the best option is ask if the key is “in” the dictionary.

    field = 'CODE'
    value = 1
    fc = r'C:\GISData\TemplateData.gdb\World\GEOGRID'
    domain_name = [f.domain for f in arcpy.ListFields(fc) if f.name.upper() == field]
    if domain_name:
        coded_values = [d.codedValues for d in arcpy.da.ListDomains(get_workspace(fc)) if d.name == domain_name[0]]
        if coded_values:
            print(value in coded_values[0])

Comments are closed.