Skip to content

Type Parsing

The pyvider.cty.parser module provides functions for parsing Terraform type strings and JSON type specifications into pyvider.cty type objects.

πŸ€– AI-Generated Content

This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.

Parser Functions

parse_tf_type_to_ctytype()

Parses a Terraform type constraint (as a Python object or string) into a CtyType instance.

Signature:

def parse_tf_type_to_ctytype(tf_type: Any) -> CtyType[Any]

Parameters: - tf_type: A Terraform type specification, which can be: - A string for primitive types: "string", "number", "bool", "dynamic" - A list with two elements [type_kind, type_spec] for collections and structural types - A nested structure for complex types

Returns: - A CtyType instance corresponding to the Terraform type

Raises: - CtyValidationError: If the type specification is invalid

Examples:

from pyvider.cty.parser import parse_tf_type_to_ctytype

# Primitive types
string_type = parse_tf_type_to_ctytype("string")
number_type = parse_tf_type_to_ctytype("number")
bool_type = parse_tf_type_to_ctytype("bool")
dynamic_type = parse_tf_type_to_ctytype("dynamic")

# Collection types (JSON array format)
list_type = parse_tf_type_to_ctytype(["list", "string"])
map_type = parse_tf_type_to_ctytype(["map", "number"])
set_type = parse_tf_type_to_ctytype(["set", "bool"])

# Object type
object_type = parse_tf_type_to_ctytype([
    "object",
    {
        "name": "string",
        "age": "number",
        "active": "bool"
    }
])

# Tuple type
tuple_type = parse_tf_type_to_ctytype([
    "tuple",
    ["string", "number", "bool"]
])

# Nested types
nested_type = parse_tf_type_to_ctytype([
    "list",
    ["object", {"id": "string", "value": "number"}]
])

parse_type_string_to_ctytype()

Alias for parse_tf_type_to_ctytype()

This function is an alias to parse_tf_type_to_ctytype() and provides identical functionality. Both names are available for backward compatibility and user preference.

from pyvider.cty.parser import parse_type_string_to_ctytype

# Same as parse_tf_type_to_ctytype()
string_type = parse_type_string_to_ctytype("string")

Note: Use parse_tf_type_to_ctytype() for clarity, as it explicitly indicates the function parses Terraform type specifications.

Type Specification Format

Terraform uses a JSON-based format to represent types:

Primitive Types

Represented as strings: - "string" β†’ CtyString() - "number" β†’ CtyNumber() - "bool" β†’ CtyBool() - "dynamic" β†’ CtyDynamic()

Collection Types

Represented as [kind, element_type]: - ["list", "string"] β†’ CtyList(element_type=CtyString()) - ["set", "number"] β†’ CtySet(element_type=CtyNumber()) - ["map", "bool"] β†’ CtyMap(element_type=CtyBool())

Structural Types

Object: ["object", {...}]

["object", {
    "attr1": "string",
    "attr2": "number"
}]

Tuple: ["tuple", [...]]

["tuple", ["string", "number", "bool"]]

Integration with Terraform

These parser functions are essential for working with Terraform:

Parsing Variable Types

from pyvider.cty.parser import parse_tf_type_to_ctytype

# Terraform variable block:
# variable "vpc_config" {
#   type = object({
#     cidr = string
#     region = string
#   })
# }

# Parse the type
vpc_type = parse_tf_type_to_ctytype([
    "object",
    {
        "cidr": "string",
        "region": "string"
    }
])

# Validate data
vpc_data = {
    "cidr": "10.0.0.0/16",
    "region": "us-east-1"
}

vpc_value = vpc_type.validate(vpc_data)

Parsing Resource Schemas

# Terraform resource schema
resource_schema_json = [
    "object",
    {
        "name": "string",
        "instance_type": "string",
        "tags": ["map", "string"]
    }
]

resource_type = parse_tf_type_to_ctytype(resource_schema_json)

# Use for validation
resource_config = {
    "name": "web-server",
    "instance_type": "t2.micro",
    "tags": {"Environment": "production"}
}

validated_config = resource_type.validate(resource_config)

Error Handling

The parser raises CtyValidationError for invalid type specifications:

from pyvider.cty.parser import parse_tf_type_to_ctytype
from pyvider.cty.exceptions import CtyValidationError

try:
    # Invalid: unknown primitive type
    invalid_type = parse_tf_type_to_ctytype("invalid_type")
except CtyValidationError as e:
    print(f"Parse error: {e}")

try:
    # Invalid: object spec must be a dict
    invalid_object = parse_tf_type_to_ctytype(["object", "not_a_dict"])
except CtyValidationError as e:
    print(f"Parse error: {e}")

Common Patterns

Parsing from JSON Configuration

import json
from pyvider.cty.parser import parse_tf_type_to_ctytype

# Load type specification from JSON file
with open("schema.json") as f:
    type_spec = json.load(f)

# Parse to CtyType
schema = parse_tf_type_to_ctytype(type_spec)

Dynamic Schema Loading

def load_schema(schema_name: str) -> CtyType:
    """Load a schema by name from configuration."""
    schemas = {
        "user": ["object", {"name": "string", "email": "string"}],
        "post": ["object", {"title": "string", "content": "string"}],
    }

    if schema_name not in schemas:
        raise ValueError(f"Unknown schema: {schema_name}")

    return parse_tf_type_to_ctytype(schemas[schema_name])

# Use it
user_type = load_schema("user")
post_type = load_schema("post")

See Also


pyvider.cty.parser

Classes

Functions

parse_tf_type_to_ctytype

parse_tf_type_to_ctytype(tf_type: Any) -> CtyType[Any]

Parses a Terraform type constraint, represented as a raw Python object (typically from JSON), into a CtyType instance.

Source code in pyvider/cty/parser.py
def parse_tf_type_to_ctytype(tf_type: Any) -> CtyType[Any]:  # noqa: C901
    """
    Parses a Terraform type constraint, represented as a raw Python object
    (typically from JSON), into a CtyType instance.
    """
    with error_boundary(
        context={
            "operation": "terraform_type_parsing",
            "tf_type": str(tf_type),
            "tf_type_python_type": type(tf_type).__name__,
        }
    ):
        if isinstance(tf_type, str):
            match tf_type:
                case "string":
                    return CtyString()
                case "number":
                    return CtyNumber()
                case "bool":
                    return CtyBool()
                case "dynamic":
                    return CtyDynamic()
                case _:
                    raise CtyValidationError(f"Unknown primitive type name: '{tf_type}'")

        if isinstance(tf_type, list) and len(tf_type) == 2:
            type_kind, type_spec = tf_type

            # Handle collection types where the spec is a single type
            if type_kind in (TYPE_KIND_LIST, TYPE_KIND_SET, TYPE_KIND_MAP):
                element_type = parse_tf_type_to_ctytype(type_spec)
                match type_kind:
                    case "list":
                        return CtyList(element_type=element_type)
                    case "set":
                        return CtySet(element_type=element_type)
                    case "map":
                        return CtyMap(element_type=element_type)

            # Handle structural types where the spec is a container
            match type_kind:
                case "object":
                    if not isinstance(type_spec, dict):
                        raise CtyValidationError(
                            f"Object type spec must be a dictionary, got {type(type_spec).__name__}"
                        )
                    attr_types = {name: parse_tf_type_to_ctytype(spec) for name, spec in type_spec.items()}
                    return CtyObject(attribute_types=attr_types)
                case "tuple":
                    if not isinstance(type_spec, list):
                        raise CtyValidationError(
                            f"Tuple type spec must be a list, got {type(type_spec).__name__}"
                        )
                    elem_types = tuple(parse_tf_type_to_ctytype(spec) for spec in type_spec)
                    return CtyTuple(element_types=elem_types)

        raise CtyValidationError(f"Invalid Terraform type specification: {tf_type}")