cloudzero-costformation
A Python library for defining CostFormation dimensions as classes and generating production-ready YAML output.
Full reference documentation for every class lives in docs/.
Features
Condition Operators
Logical:
And/Or— Logical operators with overloading support (&,|)Not— Logical negation
String Comparison:
Equals— Equality matching (single value or list)Contains— Substring or list membershipBeginsWith— Prefix matchingEndsWith— Suffix matchingMatches— Regular expression matching
Value Checking:
HasValue— Check if dimension has a value
Alphabetical Comparison:
Before/BeforeOrEquals— Less than (or equal) alphabeticallyAfter/AfterOrEquals— Greater than (or equal) alphabetically
Date:
ForDateRange— Check if data exists in a date range
Dimension Types
CoreDimension— Cloud provider primitives (Account, Service, Region, etc.)- Class names with underscores convert to colons (e.g.
K8s_Cluster→K8s:Cluster) - Cannot be serialized to YAML (only referenced)
- Class names with underscores convert to colons (e.g.
GlobalDimension— CloudZero-managed dimensions (CZ:Defined:prefix)- Cannot be serialized to YAML (only referenced)
- Inherits from
CoreDimension
GroupDimension— User-defined grouping dimensionsAllocationDimension— Telemetry and proportional allocations
Dimension Attributes
name— Display name (defaults to class name)source— Source dimension(s), single or listrules— List ofGroupRule,GroupByRule, orMetadataRuleobjectstransforms— Dimension-level transforms applied before rulesdefault_value— Fallback when no rules matchchild— Hierarchical dimension relationshipsoverride— Override another dimensionhide— Hide from UIdisable— Disable dimension from processing
Rule Types
GroupRule— Static grouping with conditions, optional rule-level source (overrides dimension source)GroupByRule— Dynamic grouping based on source values; supports transforms, conditions, and plural sources withCoalesceSourcesfor fallback logicMetadataRule— Pattern matching with substring search; supports hierarchical value patterns and optional format string for output
Transforms
Lower,Upper,Title— Case conversionSplit— Split by delimiter and extract index (optionalmaxsplit)Trim— Remove leading/trailing whitespaceClean— Remove whitespace and convert special chars to dashesNormalize— Combined lowercase + whitespace removal + normalization
Allocations
- Telemetry —
AllocateByStreamswith stream names - Rule-based —
AllocateByRuleswith anAllocationMethodofProportionalorEven
Usage
Install the library from PyPI with uv:
uv add cloudzero-costformation
Or with pip:
pip install cloudzero-costformation
The package installs as cloudzero-costformation; the import name is costformation.
Core & Global Dimensions
The library includes all core cloud provider, Kubernetes, and CloudZero-managed global dimensions from the official CFDL specification:
from costformation import (
# Core cloud provider dimensions
Account, Service, Region, Operation, UsageType,
CloudProvider, Resource,
# Kubernetes dimensions
Tag, K8s_Cluster, K8s_Namespace, K8s_Workload, K8s_Label,
# Global dimensions (CloudZero-managed)
ServiceDisplay, ResourceType, Category, InstanceType,
)
Core and global dimensions are never defined in CostFormation YAML, only referenced. Attempting to serialize them will raise a TypeError.
Cloud Provider Dimensions:
Account, BillingConnectionID, CloudProvider, CommittedUseSubscription, Description, InvoiceID, LineItemType, Operation, PayerAccount, PricingTerm, PricingUnit, PricingUnits, ProductFamily, Region, Resource, RequestType, Service, TransferType, UsageDay, UsageFamily, UsageType
Kubernetes Dimensions:
K8s_Cluster, K8s_Namespace, K8s_Workload
Dynamic Dimensions:
Tag(key)— Cloud resource tags with any key, e.g.Tag('Environment'),Tag('aws:cloudformation:stack-name')K8s_Label(name)— Kubernetes labels with any name, e.g.K8s_Label('app'),K8s_Label('node:instance-type')
Global Dimensions (CloudZero-managed):
BillingLineItem, Category, Elasticity, InstanceType, NetworkingCategory, NetworkingSubCategory, PaymentOption, ResourceDisplay, ResourceNameOnly, ResourceSummaryDisplay, ResourceSummaryID, ResourceType, ServiceDisplay, ServiceDetail, TaggableVsUntaggable
Basic Example
from costformation import (
Service,
GroupDimension,
GroupRule,
Equals,
)
class MyServices(GroupDimension):
name = 'My Services'
source = Service()
default_value = 'Other'
rules = [
GroupRule(
name='Compute',
condition=Equals(['EC2', 'Lambda', 'ECS'])
),
GroupRule(
name='Storage',
condition=Equals(['S3', 'EBS'])
),
]
dimension = MyServices()
yaml_dict = dimension.to_dict()
Output:
{
"Name": "My Services",
"Type": "Group",
"Source": "Service",
"Rules": [
{
"Type": "Group",
"Name": "Compute",
"Conditions": [{"Equals": ["EC2", "Lambda", "ECS"]}]
},
{
"Type": "Group",
"Name": "Storage",
"Conditions": [{"Equals": ["S3", "EBS"]}]
}
],
"DefaultValue": "Other"
}
Operator Overloading
from costformation import (
Category,
Contains,
GroupDimension,
GroupRule,
Lower,
Operation,
)
class AI_Operations(GroupDimension):
name = 'AI Operations'
source = Operation()
transforms = [Lower()]
default_value = 'Non-AI'
rules = [
GroupRule(
name='Input',
condition=(
Category().equals('AI') &
Contains(['input', 'prompt'])
)
),
]
No Top-Level Source
class ResourceName(GroupDimension):
name = 'Resource Name'
source = None
override = ResourceNameOnly()
rules = [
GroupByRule(
source=ResourceDisplay(),
conditions=[Not(BeginsWith('billingitem-'))]
),
]
Rule-Level Source
# CustomerNames_Allocation and Customer are user-defined dimensions
# (definitions omitted for brevity)
class Customer_Names(GroupDimension):
name = 'Customer Names'
source = None
rules = [
GroupByRule(source=CustomerNames_Allocation()),
GroupRule(
name='CloudZero',
source=Customer(),
condition=Equals('00000000-0000-0000-0000-000000000000')
),
]
Allocation Dimensions
class AI_Telemetry(AllocationDimension):
name = 'AI Telemetry'
hide = True
streams = ['cost-per-ai-call', 'ai-token-metrics']
class RuleBasedAlloc(AllocationDimension):
name = 'Rule-based Allocation'
allocation_method = AllocationMethod.PROPORTIONAL
spend_to_allocate = [Service().equals('AmazonEC2')]
across_elements = [
GroupRule(name='by-account', condition=Account().begins_with('prod-')),
]
Evaluation
Dimensions can be evaluated against test data:
test_data = {
'Service': 'Lambda',
'Category': 'AI',
'Operation': 'RunInput'
}
result = MyServices.evaluate(test_data)
# Returns: 'Compute' (matches the Lambda rule)
Development
Dependency Management
Set up a development environment
With uv installed, create the virtual environment at ./.venv and install all dependencies with:
make init
There's no need to activate the environment — uv run and the make targets below use it automatically. To pin a specific Python version, run uv venv -p 3.12 ./.venv first.
Updating Dependencies
We uv lock requested dependencies from the pyproject.toml file into a deterministic uv.lock file.
For more information about managing dependencies with uv, see the official docs.
Library Dependencies
These are dependencies your library needs when a client installs it.
If you want to edit library dependencies, simply edit the project.dependencies value in pyproject.toml, or use the uv add command to do it for you, eg. uv add "pydantic~=2.0".
Development Dependencies
Development dependencies are dependencies needed for development only, eg tests or linting.
If you want to edit development dependencies, then add the dependency to the appropriate dependency-group in pyproject.toml.
Alternatively, you can use uv add to edit the file for you eg, run uv add --group lint ruff.
Locking Dependencies
Whenever you update dependencies, you should be sure to run make lock-requirements in order to ensure reproducible development environments.
Whenever dependencies are updated, make sure to run make init to sync your virtual environment.
Checks
Linting
You can run all the python linting (mypy, ruff) with:
make lint
Then auto-fix linting errors with:
make lint-fix
Unit Tests
You can run all the python tests with pytest:
make test
Full Validation
You can run both linting and testing with:
make check
Publishing new versions of the package
Publishing to PyPI is done by the publish-to-pypi.yml workflow (using Trusted Publishing) whenever a GitHub Release is published:
- Open a PR that bumps
__version__incostformation/__init__.pyand adds a matching section toCHANGELOG.md(CI enforces both). - Merge it, then create a GitHub Release from
mainwith a tag matching the new version. - The workflow builds the package with uv and publishes it to PyPI.
License
This project is licensed under the Apache License, Version 2.0 — see the LICENSE file for details.
Trademarks
"CloudZero" and the CloudZero logo are trademarks of CloudZero, Inc. Use of these trademarks is limited to identification and attribution as required by the Apache License. You may not use CloudZero trademarks in a way that suggests endorsement or affiliation without written permission.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloudzero_costformation-0.1.0.tar.gz.
File metadata
- Download URL: cloudzero_costformation-0.1.0.tar.gz
- Upload date:
- Size: 53.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ad8348b2871a06bcab348010afc95ef038dcc023de56537d36b8e6bacb5e1d8
|
|
| MD5 |
8268eb6a7696be9de5d9fd830e2d7e46
|
|
| BLAKE2b-256 |
af48ec66bd9849a103988ac8bb64df0c60f9ae7f05b8def17df8dbf0a15e4565
|
Provenance
The following attestation bundles were made for cloudzero_costformation-0.1.0.tar.gz:
Publisher:
publish-to-pypi.yml on Cloudzero/cloudzero-costformation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cloudzero_costformation-0.1.0.tar.gz -
Subject digest:
2ad8348b2871a06bcab348010afc95ef038dcc023de56537d36b8e6bacb5e1d8 - Sigstore transparency entry: 2554810691
- Sigstore integration time:
-
Permalink:
Cloudzero/cloudzero-costformation@0b849a66cb8068c377d809b3e3ecbc87fe2978c3 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Cloudzero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@0b849a66cb8068c377d809b3e3ecbc87fe2978c3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cloudzero_costformation-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cloudzero_costformation-0.1.0-py3-none-any.whl
- Upload date:
- Size: 37.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b7ac0f670fbbfcd75b5866c1bf2442322b02be3419f6a2890f6be11e9015ca1
|
|
| MD5 |
5561f0b84beac2795adfe178bece17e9
|
|
| BLAKE2b-256 |
cfc4b1e06854b9d4a25930715c1e497569cb30cb4f670ded3dd56fdb295e0618
|
Provenance
The following attestation bundles were made for cloudzero_costformation-0.1.0-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on Cloudzero/cloudzero-costformation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cloudzero_costformation-0.1.0-py3-none-any.whl -
Subject digest:
3b7ac0f670fbbfcd75b5866c1bf2442322b02be3419f6a2890f6be11e9015ca1 - Sigstore transparency entry: 2554810718
- Sigstore integration time:
-
Permalink:
Cloudzero/cloudzero-costformation@0b849a66cb8068c377d809b3e3ecbc87fe2978c3 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Cloudzero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@0b849a66cb8068c377d809b3e3ecbc87fe2978c3 -
Trigger Event:
release
-
Statement type: