
## Manage options (enumerations)

URL: https://docs.atlan.com/product/capabilities/build-apps/sdks/python/custom-metadata/how-tos/manage-enumerations

> Create and manage option sets (enumerations) for custom metadata attributes in Atlan using the Python SDK — define valid value sets like data quality dimensions using EnumDef.creator().

# EnumDef: create and manage enumeration options

Use `EnumDef` in the Atlan Python SDK to programmatically create and manage enumeration type definitions used in custom metadata attributes.

Options (or *enumerations*) in Atlan allow you to define a set of valid values
for custom metadata attributes. Like other objects in the SDK, enumerations implement
the builder pattern. This allows you to progressively build-up the list of values you want to create.

## Build minimal object needed

For example, to create an enumeration to capture a data quality dimension:

### Java

```java showLineNumbers title="Build enumeration for creation"
EnumDef enumDef = EnumDef.creator(
 "DataQualityDimensions", // (1)
 List.of("Accuracy", "Completeness", "Consistency", "Timeliness", "Validity", "Uniqueness")) // 2
 .build(); // (3)
```

1. When creating the enumeration, you must provide a name (`DataQualityDimensions` in this example).
2. You can then add as many valid values as you want: always as a list of strings.
3. As with all other builder patterns, you must `build()` the object you've defined.

### Python

```python showLineNumbers title="Build enumeration for creation"
from pyatlan.model.typedef import EnumDef

enum_def = EnumDef.create(
 name="DataQualityDimensions", # (1)
 values=["Accuracy", "Completeness", "Consistency", "Timeliness", "Validity", "Uniqueness"] # (2)
)
```

1. When creating the enumeration, you must provide a name (`DataQualityDimensions` in this example).
2. You can then add as many valid values as you want: always as a list of strings.

### Kotlin

```kotlin showLineNumbers title="Build enumeration for creation"
val enumDef = EnumDef.creator(
 "DataQualityDimensions", // (1)
 listOf("Accuracy", "Completeness", "Consistency", "Timeliness", "Validity", "Uniqueness")) // 2
 .build() // (3)
```

1. When creating the enumeration, you must provide a name (`DataQualityDimensions` in this example).
2. You can then add as many valid values as you want: always as a list of strings.
3. As with all other builder patterns, you must `build()` the object you've defined.

### Raw REST API

```json showLineNumbers title="POST /api/meta/types/typedefs"
{
 "enumDefs": [ // (1),
 {
 "value": "Completeness",
 "ordinal": 1
 },
 {
 "value": "Consistency",
 "ordinal": 2
 },
 {
 "value": "Timeliness",
 "ordinal": 3
 },
 {
 "value": "Validity",
 "ordinal": 4
 },
 {
 "value": "Uniqueness",
 "ordinal": 5
 }
 ]
 }
 ]
}
```

1. All enumeration definitions must be specified within the `enumDefs` array.
2. Each definition must be defined with a category set to `ENUM`.
3. The name you provide for the definition will be used both for the front and back-end.
4. Within the definition, you need to define each valid value for the enumeration within the `elementDefs` array. Each valid value should have both a string `value` (as it will appear in the UI) and an integer `ordinal`. Both must be unique within the enumeration.

## Create enumeration from object

Now that the object is built, this `enumDef` object will have the required information for Atlan to create it.
You can then actually create the enumeration in Atlan by calling the `create()` method on the object itself:

### Java

```java title="Create the enumeration"
EnumDef response = enumDef.create(client); // (1)
```

1. The `create()` operation will actually create the enumeration within Atlan, including all the valid values that were defined as part of it. Because this operation will persist the structure in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Python

```python title="Create the enumeration"
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()
response = client.typedef.create(enum_def) # (1)
```

1. The `typedef.create()` operation will actually create the enumeration definition within Atlan, including all the valid values that were defined as part of it.

### Kotlin

```kotlin title="Create the enumeration"
val response = enumDef.create(client) // (1)
```

1. The `create()` operation will actually create the enumeration within Atlan, including all the valid values that were defined as part of it. Because this operation will persist the structure in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Raw REST API

:::tip[Creation implicit in step above]
The actual creation of the enumeration structure is implicit in the example above.
:::

## Use enumeration in custom metadata definition

To use an enumeration to restrain the values for an attribute in a custom metadata definition:

### Java

```java title="Build custom metadata definition for creation"
CustomMetadataDef customMetadataDef = CustomMetadataDef.creator("DQ") // (1)
 .attributeDef( // (2)
 AttributeDef.of(client, "Dimension", // (3)
 AtlanCustomAttributePrimitiveType.OPTIONS, // (4)
 "DataQualityDimensions", // (5)
 false)) // (6)
 .options(CustomMetadataOptions.withLogoAsEmoji("🔖")) // (7)
 .build(); // (8)
customMetadataDef.create(); // (9)
```

1. When creating the custom metadata structure, you must provide a name (`DQ` in this example).
2. You can then add as many attributes to that structure as you want.
3. Each attribute must have a name. Because this operation may need to retrieve information from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.
4. Each attribute must have a type. When using the enumeration as the type (to constrain its possible values), use `AtlanCustomAttributePrimitiveType.OPTIONS` as the type.
5. You must then also specify the enumeration that defines the valid values for this attribute. Carrying on the same example, we give the name of the enumeration here: `DataQualityDimensions`.
6. You must also specify whether the attribute allows multiple values to be captured on it (`true`) or only a single value (`false`).
7. You can specify how the custom metadata should appear (in this case, with an emoji).
8. As with all other builder patterns, you must `build()` the object you've defined.
9. Then you can `create()` the custom metadata definition within Atlan, including this enumeration-constrained attribute that was defined as part of it.

### Python

```python title="Build custom metadata definition for creation"
from pyatlan.model.typedef import AttributeDef, CustomMetadataDef
from pyatlan.model.enums import AtlanCustomAttributePrimitiveType
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()

cm_def = CustomMetadataDef.create(display_name="DQ") # (1)
cm_def.attribute_defs = [ # (2)
 AttributeDef.create(
 client=client, # (3)
 display_name="Dimension", # (4)
 attribute_type=AtlanCustomAttributePrimitiveType.OPTIONS, # (5)
 options_name="DataQualityDimensions", # (6)
 ),
]
cm_def.options = CustomMetadataDef.Options.with_logo_as_emoji( # (7)
 emoji="🔖"
)
client.typedef.create(cm_def) # (8)
```

1. When creating the custom metadata structure, you must provide a name (`DQ` in this example).
2. You can then add as many attributes to that structure as you want.
3. You must provide a client instance.
4. Each attribute must have a name.
5. Each attribute must have a type. When using the enumeration as the type (to constrain its possible values), use `AtlanCustomAttributePrimitiveType.OPTIONS` as the type.
6. You must then also specify the enumeration that defines the valid values for this attribute. Carrying on the same example, we give the name of the enumeration here: `DataQualityDimensions`.
7. You can specify how the custom metadata should appear (in this case, with an emoji).
8. Then you can create the custom metadata definition within Atlan, including this enumeration-constrained attribute that was defined as part of it.

### Kotlin

```kotlin title="Build custom metadata definition for creation"
val customMetadataDef = CustomMetadataDef.creator("DQ") // (1)
 .attributeDef( // (2)
 AttributeDef.of(client, "Dimension", // (3)
 AtlanCustomAttributePrimitiveType.OPTIONS, // (4)
 "DataQualityDimensions", // (5)
 false)) // (6)
 .options(CustomMetadataOptions.withLogoAsEmoji("🔖")) // (7)
 .build() // (8)
customMetadataDef.create() // (9)
```

1. When creating the custom metadata structure, you must provide a name (`DQ` in this example).
2. You can then add as many attributes to that structure as you want.
3. Each attribute must have a name. Because this operation may need to retrieve information from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.
4. Each attribute must have a type. When using the enumeration as the type (to constrain its possible values), use `AtlanCustomAttributePrimitiveType.OPTIONS` as the type.
5. You must then also specify the enumeration that defines the valid values for this attribute. Carrying on the same example, we give the name of the enumeration here: `DataQualityDimensions`.
6. You must also specify whether the attribute allows multiple values to be captured on it (`true`) or only a single value (`false`).
7. You can specify how the custom metadata should appear (in this case, with an emoji).
8. As with all other builder patterns, you must `build()` the object you've defined.
9. Then you can `create()` the custom metadata definition within Atlan, including this enumeration-constrained attribute that was defined as part of it.

### Raw REST API

```json showLineNumbers title="POST /api/meta/types/typedefs"
{
 "businessMetadataDefs": [
 {
 "category": "BUSINESS_METADATA",
 "name": "DQ", // (1)
 "attributeDefs": [ // (2),
 "isNew": true,
 "enumValues": [
 "Accuracy",
 "Completeness",
 "Consistency",
 "Timeliness",
 "Validity",
 "Uniqueness"
 ]
 }
 ],
 "displayName": "DQ",
 "options": {
 "logoType": "emoji",
 "emoji": "🔖"
 }
 }
 ]
}
```

1. When creating the custom metadata structure, you must provide a name (`DQ` in this example).
2. You can then add as many attributes to that structure as you want.
3. Each attribute must have a name. Note, however, that the `name` should be sent as an empty string when creating an attribute (the name will be generated by the back-end), and it's actually the `displayName` that gives the name as it will appear in the UI.
4. You must specify the enumeration that defines the valid values for this attribute. Carrying on the same example, we give the name of the enumeration here: `DataQualityDimensions`.
5. Each attribute must also have a primitive type. When using the enumeration as the type (to constrain its possible values), use:

 - `enum` as the primitive type
 - `isEnum` set to `true`
 - and set `enumType` to the name of the enumeration

## Update options (enumerations)

For example, to update our data quality dimension
enumeration by adding a new set of valid values.

### Java

```java showLineNumbers title="Update existing enum structure"
EnumDef enumDef = EnumDef.updater(
 client, "DataQualityDimensions", // (1)
 List.of("Unknown", "Others"), // (2)
 false // (3)
 ).build(); // (4)

EnumDef response = enumDef.update(client); // (5)
```

1. When updating the existing enumeration, you must provide a name (`DataQualityDimensions` in this example). Because this operation may need to retrieve information from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.
2. You can then add as many valid values as you want: always as a list of strings.
3. You must specify whether you want to replace all existing values in the enumeration with the new ones (`true`), or if the new ones will be appended to the existing set (`false`).
4. As with all other builder patterns, you must `build()` the object you've defined.
5. The `update()` operation will actually update the enumeration within Atlan, including all the valid values that were defined as part of it. Because this operation will persist the structure in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Python

```python showLineNumbers title="Update existing enum structure"
from pyatlan.model.typedef import EnumDef
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()

enum_def = EnumDef.update(
 client=client,
 name="DataQualityDimensions", # (1)
 values=["Unknown", "Others"] # (2)
 replace_existing=False # (3)
)

response = client.typedef.update(enum_def) # (4)
```

1. When updating the existing enumeration, you must provide
a name (`DataQualityDimensions` in this example).
2. You can then add as many valid values as you want: always as a list of strings.
3. You must specify whether you want to replace all existing values in the enumeration
with the new ones (`True`), or if the new ones will be appended to the existing set (`False`).
4. The `client.typedef.update()` operation will actually update the enumeration within Atlan,
including all the valid values that were defined as part of it.

### Kotlin

```kotlin showLineNumbers title="Update existing enum structure"
val enumDef = EnumDef.updater(
 client, "DataQualityDimensions", // (1)
 listOf("Unknown", "Others"), // (2)
 false // (3)
 ).build() // (4)

val response = enumDef.update(client) // (5)
```

1. When updating the existing enumeration, you must provide a name (`DataQualityDimensions` in this example). Because this operation may need to retrieve information from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.
2. You can then add as many valid values as you want: always as a list of strings.
3. You must specify whether you want to replace all existing values in the enumeration with the new ones (`true`), or if the new ones will be appended to the existing set (`false`).
4. As with all other builder patterns, you must `build()` the object you've defined.
5. The `update()` operation will actually update the enumeration within Atlan, including all the valid values that were defined as part of it. Because this operation will persist the structure in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Raw REST API

```json showLineNumbers title="PUT /api/meta/types/typedefs"
{
 "enumDefs": [ // (1),
 {
 "value": "Completeness",
 "ordinal": 1
 },
 {
 "value": "Consistency",
 "ordinal": 2
 },
 {
 "value": "Timeliness",
 "ordinal": 3
 },
 {
 "value": "Validity",
 "ordinal": 4
 },
 {
 "value": "Uniqueness",
 "ordinal": 5
 },
 {
 "value": "Unknown",
 "ordinal": 6
 },
 {
 "value": "Others",
 "ordinal": 7
 }
 ]
 }
 ]
}
```

1. All enumeration definitions must be specified within the `enumDefs` array.
2. Each definition must be defined with a category set to `ENUM`.
3. The name of the enumeration definition you want to update.
4. You must send all valid values in the `elementDefs` array, as the existing list
of elements for the enumerations will be entirely replaced by what you provide here.

## Retrieve options (enumerations)

To retrieve options (enumeration) by name:

### Java

```java showLineNumbers title="Retrieve existing enum structure"
TypeDef enumDef = client.typeDefs.get("DataQualityDimensions"); // (1)
```

1. To retrieve the enumeration, you need to call the `.typeDefs.get()` method on a client, with the human-readable name of the enumeration.

### Python

```python showLineNumbers title="Retrieve existing enum structure"
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()
enum_def = client.typedef.get_by_name("DataQualityDimensions") # (1)
```

1. To retrieve the enumeration, you need to call the
`client.typedef.get_by_name()` method with its human-readable name.

### Kotlin

```kotlin showLineNumbers title="Retrieve existing enum structure"
val enumDef = client.typeDefs.get("DataQualityDimensions") // (1)
```

1. To retrieve the enumeration, you need to call the `.typeDefs.get()` method on a client, with the human-readable name of the enumeration.

### Raw REST API

```json showLineNumbers title="GET /api/meta/types/typedef/name/DataQualityDimensions"
```

:::tip[Options (enumerations) don't have a hashed-string representation]
Note that unlike a custom metadata structure, options (enumerations) don't have
a hashed-string name. Therefore, use their human-readable name when retrieving its structure.

:::warning[URL-encoding]
However, since this name is embedded in the URL for retrieval,
it does need to be url-encoded. For example, if the name contains
spaces these need to be replaced with `%20`.
:::
:::

## Retrieve all options (enumerations)

To retrieve all options (enumeration):

### Java

```java showLineNumbers title="Retrieve all enum structures"
TypeDefResponse enumDefs = client.typeDefs.list(AtlanTypeCategory.ENUM); // (1)
```

1. To retrieve all enumerations, call the `.typeDefs.list()` method on a client, with the category `AtlanTypeCategory.ENUM`.

### Python

```python showLineNumbers title="Retrieve all enum structures"
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()
response = client.typedef.get(type_category=AtlanTypeCategory.ENUM) # (1)
enum_defs = response.enum_defs # (2)
```

1. To retrieve all enumerations, call the `client.typedef.get()`
method with the definition category `AtlanTypeCategory.ENUM`.
2. Specifically retrieve the list of enumerations from `TypeDefResponse`.

### Kotlin

```kotlin showLineNumbers title="Retrieve all enum structures"
val enumDefs = client.typeDefs.list(AtlanTypeCategory.ENUM) // (1)
```

1. To retrieve all enumerations, call the `.typeDefs.list()` method on a client, with the category `AtlanTypeCategory.ENUM`.

### Raw REST API

```json showLineNumbers title="GET /api/meta/types/typedefs/?type=ENUM"
```

## Delete options (enumerations)

To delete options (enumeration):

### Java

```java showLineNumbers title="Delete enum structure"
EnumDef.purge(client, "DataQualityDimensions"); // (1)
```

1. You only need to call the `EnumDef.purge()` method with the human-readable name of the enumeration, and it will be deleted. Because this operation will remove the structure from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Python

```python showLineNumbers title="Delete enum structure"
from pyatlan.model.typedef import EnumDef
from pyatlan.client.atlan import AtlanClient

client = AtlanClient()
client.typedef.purge("DataQualityDimensions", EnumDef) # (1)
```

1. You only need to call the `clietn.typedef.purge()` method
with the human-readable name of the enumeration, and it will be deleted.

### Kotlin

```kotlin showLineNumbers title="Delete enum structure"
EnumDef.purge("DataQualityDimensions") // (1)
```

1. You only need to call the `EnumDef.purge()` method with the human-readable name of the enumeration, and it will be deleted. Because this operation will remove the structure from Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Raw REST API

```json showLineNumbers title="DELETE /api/meta/types/typedef/name/DataQualityDimensions"
```

:::tip[Options (enumerations) don't have a hashed-string representation]
Note that unlike a custom metadata structure, options (enumerations)
don't have a hashed-string name. Therefore, use their human-readable name when deleting.

:::warning[URL-encoding]
However, since this name is embedded in the URL for deletion,
it does need to be url-encoded. For example, if the name contains
spaces these need to be replaced with `%20`.
:::
:::

---
