Skip to content

pyvider-hcl Architecture

This document provides a visual and detailed overview of the pyvider-hcl architecture.

๐Ÿค– 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.

System Overview

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         User Application                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      pyvider.hcl Package                         โ”‚
โ”‚                                                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚
โ”‚  โ”‚  parser/         โ”‚  โ”‚  factories/      โ”‚  โ”‚  output/       โ”‚โ”‚
โ”‚  โ”‚  โ”œโ”€ base.py     โ”‚  โ”‚  โ”œโ”€ types.py     โ”‚  โ”‚  โ””โ”€ formatting โ”‚โ”‚
โ”‚  โ”‚  โ”œโ”€ inference.pyโ”‚  โ”‚  โ”œโ”€ variables.py โ”‚  โ”‚      .py       โ”‚โ”‚
โ”‚  โ”‚  โ””โ”€ context.py  โ”‚  โ”‚  โ””โ”€ resources.py โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ”‚                  โ”‚  โ”‚                  โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ”‚ โ€ข parse_hcl_    โ”‚  โ”‚ โ€ข create_        โ”‚  โ”‚ โ€ข pretty_print โ”‚โ”‚
โ”‚  โ”‚   to_cty()      โ”‚  โ”‚   variable_cty   โ”‚  โ”‚   _cty()       โ”‚โ”‚
โ”‚  โ”‚ โ€ข parse_with_   โ”‚  โ”‚ โ€ข create_        โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ”‚   context()     โ”‚  โ”‚   resource_cty   โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ”‚ โ€ข auto_infer_   โ”‚  โ”‚ โ€ข parse_hcl_     โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ”‚   cty_type()    โ”‚  โ”‚   type_string()  โ”‚  โ”‚                โ”‚โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚
โ”‚                                                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   โ”‚
โ”‚  โ”‚  terraform/      โ”‚  โ”‚  exceptions.py   โ”‚                   โ”‚
โ”‚  โ”‚  โ””โ”€ config.py    โ”‚  โ”‚  โ€ข HclError      โ”‚                   โ”‚
โ”‚  โ”‚                  โ”‚  โ”‚  โ€ข HclParsing    โ”‚                   โ”‚
โ”‚  โ”‚ โ€ข parse_         โ”‚  โ”‚    Error         โ”‚                   โ”‚
โ”‚  โ”‚   terraform_     โ”‚  โ”‚                  โ”‚                   โ”‚
โ”‚  โ”‚   config()       โ”‚  โ”‚                  โ”‚                   โ”‚
โ”‚  โ”‚   (placeholder)  โ”‚  โ”‚                  โ”‚                   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚               โ”‚               โ”‚
                โ–ผ               โ–ผ               โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  python-hcl2     โ”‚ โ”‚ pyvider-cty  โ”‚ โ”‚ provide-         โ”‚
    โ”‚  (HCL parser)    โ”‚ โ”‚ (type system)โ”‚ โ”‚ foundation       โ”‚
    โ”‚                  โ”‚ โ”‚              โ”‚ โ”‚ (errors/logging) โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Module Breakdown

1. Parser Subpackage (parser/)

Modules: - base.py: Core parsing logic - contains parse_hcl_to_cty() - inference.py: Type inference - contains auto_infer_cty_type() - context.py: Enhanced error context - contains parse_with_context()

Responsibilities: - Parse HCL strings into Python data structures - Convert Python data to CTY types - Automatic type inference - Schema validation

Data Flow:

HCL String
    โ†“
parse_hcl_to_cty() [base.py]
    โ†“
python-hcl2.loads()  โ”€โ”€โ†’  Python dict/list
    โ†“
Schema provided?
    โ”œโ”€ Yes โ†’ schema.validate(data)  โ”€โ”€โ†’  CtyValue
    โ””โ”€ No  โ†’ auto_infer_cty_type() [inference.py]  โ”€โ”€โ†’  CtyValue

Key Functions: - parse_hcl_to_cty(hcl_content, schema=None) โ†’ CtyValue (base.py) - parse_with_context(content, source_file=None) โ†’ dict (context.py) - auto_infer_cty_type(raw_data) โ†’ CtyValue (inference.py)


2. Factories Subpackage (factories/)

Modules: - types.py: Type string parsing - contains parse_hcl_type_string() - variables.py: Variable factory - contains create_variable_cty() - resources.py: Resource factory - contains create_resource_cty()

Responsibilities: - Create Terraform variable structures - Create Terraform resource structures - Parse HCL type strings into CTY types

Type String Parsing Flow:

Type String (e.g., "list(string)")
    โ†“
parse_hcl_type_string() [types.py]
    โ”œโ”€ Primitive? โ†’ Return CtyString/CtyNumber/CtyBool
    โ”œโ”€ list(T)?   โ†’ Return CtyList(element_type=T)
    โ”œโ”€ map(T)?    โ†’ Return CtyMap(element_type=T)
    โ””โ”€ object({})?โ†’ Parse attributes โ†’ Return CtyObject

Variable Creation Flow:

Python inputs
    โ†“
create_variable_cty() [variables.py]
    โ†“
Parse type_str โ†’ CtyType [types.py]
    โ†“
Validate default against type
    โ†“
Build Terraform variable structure
    โ†“
Validate with schema โ†’ CtyValue

Key Functions: - create_variable_cty(name, type_str, default_py=None, ...) โ†’ CtyValue (variables.py) - create_resource_cty(r_type, r_name, attributes_py, ...) โ†’ CtyValue (resources.py) - parse_hcl_type_string(type_str) โ†’ CtyType (types.py)


3. Output Subpackage (output/)

Modules: - formatting.py: CTY value formatting - contains pretty_print_cty()

Responsibilities: - Format CTY values for human-readable display - Handle nested structures (objects, lists, maps, tuples)

Printing Flow:

CtyValue
    โ†“
pretty_print_cty() [formatting.py]
    โ†“
_pretty_print_cty_recursive()
    โ”œโ”€ CtyObject  โ†’ Format as JSON object
    โ”œโ”€ CtyList    โ†’ Format as JSON array
    โ”œโ”€ CtyMap     โ†’ Format as JSON object
    โ”œโ”€ CtyTuple   โ†’ Format as JSON array
    โ””โ”€ Primitive  โ†’ Format as string/number/bool

Key Functions: - pretty_print_cty(value) โ†’ None (prints to stdout) (formatting.py)


4. Terraform Subpackage (terraform/)

Modules: - config.py: Terraform configuration parsing - contains parse_terraform_config()

Status: Placeholder for future implementation

Planned Responsibilities: - Parse Terraform-specific blocks (provider, module, data, etc.) - Handle Terraform configuration files - Validate Terraform-specific structures

Current: - parse_terraform_config(config_path) returns placeholder (config.py)


5. Exceptions Module (exceptions.py)

Responsibilities: - Define custom exception types - Provide structured error information - Integrate with provide-foundation error handling

Exception Hierarchy:

provide.foundation.FoundationError
    โ†“
HclError (base class)
    โ†“
HclParsingError
    โ”œโ”€ message: str
    โ”œโ”€ source_file: str | None
    โ”œโ”€ line: int | None
    โ””โ”€ column: int | None


Data Flow Examples

Example 1: Parse HCL with Schema

User Code:
  hcl_string = 'name = "test"'
  schema = CtyObject({"name": CtyString()})
  result = parse_hcl_to_cty(hcl_string, schema)

Flow:
  1. parse_hcl_to_cty() receives string and schema
  2. python-hcl2.loads() parses HCL โ†’ {"name": "test"}
  3. schema.validate({"name": "test"}) validates
  4. Returns CtyValue with type=CtyObject, value={"name": CtyString("test")}

Example 2: Create Terraform Variable

User Code:
  var = create_variable_cty(
      name="region",
      type_str="string",
      default_py="us-west-2"
  )

Flow:
  1. create_variable_cty() receives params
  2. _parse_hcl_type_string("string") โ†’ CtyString()
  3. CtyString().validate("us-west-2") โ†’ validates
  4. Build structure: {"variable": [{"region": {...}}]}
  5. Create schema for validation
  6. Return validated CtyValue

Example 3: Automatic Type Inference

User Code:
  hcl = '''
    name = "example"
    count = 5
    enabled = true
  '''
  result = parse_hcl_to_cty(hcl)

Flow:
  1. parse_hcl_to_cty() with no schema
  2. python-hcl2.loads() โ†’ {"name": "example", "count": 5, "enabled": true}
  3. auto_infer_cty_type() walks the data:
     - "example" โ†’ CtyString
     - 5 โ†’ CtyNumber
     - true โ†’ CtyBool
  4. Build CtyObject with inferred types
  5. Return CtyValue

Type System Integration

CTY Type Mapping

HCL Type String    โ†’    CTY Type
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
"string"           โ†’    CtyString()
"number"           โ†’    CtyNumber()
"bool"             โ†’    CtyBool()
"any"              โ†’    CtyDynamic()
"list(string)"     โ†’    CtyList(element_type=CtyString())
"map(number)"      โ†’    CtyMap(element_type=CtyNumber())
"object({...})"    โ†’    CtyObject(attributes={...})

Python to CTY Inference

Python Value       โ†’    CTY Type
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
str                โ†’    CtyString()
int/float/Decimal  โ†’    CtyNumber()
bool               โ†’    CtyBool()
None               โ†’    CtyDynamic()
list               โ†’    CtyList(CtyDynamic())
dict               โ†’    CtyObject({...})

Error Handling Flow

Error Occurs
    โ†“
Which layer?
    โ”œโ”€ HCL Parsing โ†’ python-hcl2 exception
    โ”‚                    โ†“
    โ”‚               Caught by parse_hcl_to_cty()
    โ”‚                    โ†“
    โ”‚               Wrapped in HclParsingError
    โ”‚
    โ”œโ”€ Schema Validation โ†’ CtyValidationError
    โ”‚                          โ†“
    โ”‚                     Caught by parse_hcl_to_cty()
    โ”‚                          โ†“
    โ”‚                     Wrapped in HclParsingError
    โ”‚
    โ””โ”€ Factory โ†’ HclFactoryError
                     โ†“
                Raised directly
                     โ†“
User catches exception with:
    - Descriptive message
    - Source location (if available)
    - Original error context

Performance Characteristics

Current Implementation: - Parsing: O(n) where n = HCL content size (via python-hcl2) - Type Inference: O(m) where m = number of fields in data structure - Schema Validation: O(m) for field validation - No caching: Each parse is independent - No lazy evaluation: All parsing happens immediately

Memory Usage: - HCL string kept in memory - Full parse tree created in memory - CTY objects created for all values - Typical: ~2-5x HCL string size


Extension Points

To Add New Features:

  1. New Parser Functions:
  2. Add to appropriate module in parser/ subpackage
  3. Export in __init__.py
  4. Add tests in tests/parser/test_parser.py

  5. New Factory Types:

  6. Add factory function to appropriate module in factories/ subpackage
  7. Export in __init__.py
  8. Add tests in tests/factories/test_factories.py

  9. New Type Support:

  10. Extend parse_hcl_type_string() in factories/types.py
  11. Update PRIMITIVE_TYPE_MAP or COMPLEX_TYPE_REGEX
  12. Add corresponding CTY types from pyvider-cty

  13. Terraform Features:

  14. Implement in appropriate module in terraform/ subpackage
  15. May need new parsing logic
  16. Will integrate with existing parser/factory modules

Dependencies

Runtime Dependencies: - python-hcl2>=7.2.1 - Core HCL parsing - pyvider-cty>=0.0.113 - Type system - provide-foundation>=0.0.0 - Error handling/logging - attrs>=25.3.0 - Structured exceptions - regex>=2024.11.6 - Enhanced regex

Development Dependencies: - pytest - Testing framework - pytest-xdist - Parallel test execution - ruff - Linting and formatting - mypy - Type checking - provide-testkit[standard,advanced-testing,typecheck,build] - Test utilities


Design Principles

  1. Simplicity: Focused API with minimal abstractions
  2. Type Safety: All values go through CTY type system
  3. Error Context: Rich error messages with source locations
  4. Composability: Small, focused modules that work together
  5. Extensibility: Clear extension points for future features
  6. Testability: All functions are pure and easily testable