Skip to main content

dimcalc

A Python library for calculating dimensional (volumetric) weight and selecting optimal shipping boxes.

Features

  • Calculate dimensional weight using configurable DIM factors
  • Select optimal shipping boxes from a list of available sizes
  • Distribute chargeable weight proportionally across products
  • Built with Pydantic for data validation
  • Type hints throughout for IDE support

Installation

pip install dimcalc

Quick Start

Basic Dimensional Weight Calculation

from dimcalc import DimCalc, Dimensions

# Create a calculator with your carrier's DIM factor
calc = DimCalc(dimensional_factor=5.0)  # 5.0 for cm³ to grams

# Define product dimensions (in centimeters)
dims = Dimensions(length=30, width=20, height=10)

# Calculate chargeable weight
result = calc.calculate_chargeable_weight(
    actual_weight=500,  # grams
    dimensions=dims,
    quantity=2
)

print(f"Actual weight: {result.actual_weight}g")
print(f"Dimensional weight: {result.dimensional_weight}g")
print(f"Chargeable weight: {result.chargeable_weight}g")
print(f"Using dimensional: {result.is_dimensional_used}")

Box Selection

from dimcalc import BoxSelector, Box, Product, Dimensions

# Define your available box sizes
boxes = [
    Box(id="small", length=20, width=15, height=10, name="Small"),
    Box(id="medium", length=30, width=25, height=15, name="Medium"),
    Box(id="large", length=40, width=30, height=20, name="Large"),
]

# Create a selector with 20% volume buffer for packing inefficiency
selector = BoxSelector(boxes=boxes, volume_buffer_percentage=20.0)

# Define products to ship
products = [
    Product(
        weight=500,  # grams per unit
        quantity=2,
        dimensions=Dimensions(length=15, width=10, height=8)
    ),
    Product(
        weight=300,
        quantity=1,
        dimensions=Dimensions(length=10, width=10, height=5)
    ),
]

# Select optimal box
result = selector.select_box(products)

print(f"Selected box: {result.box.name}")
print(f"Chargeable weight: {result.weight.chargeable_weight}g")
print(f"Box utilization: {result.utilization_percentage:.1f}%")

Weight Distribution

When using box-based calculation, distribute the chargeable weight back to individual products:

from dimcalc import WeightDistributor

# After box selection...
distributed = WeightDistributor.distribute(products, result)

for i, dist in enumerate(distributed):
    print(f"Product {i+1}: {dist.distributed_weight}g per unit")

API Reference

Models

Dimensions

Represents physical dimensions in centimeters.

dims = Dimensions(length=30, width=20, height=10)
dims.volume        # 6000.0 (cm³)
dims.max_dimension # 30.0

Box

Represents a shipping box.

box = Box(
    id="box_1",           # Unique identifier
    length=30,            # cm
    width=20,             # cm
    height=10,            # cm
    name="Medium Box"     # Optional display name
)
box.volume         # 6000.0 (cm³)
box.max_dimension  # 30.0
box.dimensions     # Returns Dimensions object

Product

Represents a product for weight/box calculation.

product = Product(
    weight=500,                    # grams per unit
    quantity=2,                    # number of units (default: 1)
    dimensions=Dimensions(...)     # optional dimensions
)
product.total_weight  # 1000 (weight × quantity)
product.total_volume  # volume × quantity (or None if no dimensions)

WeightResult

Result of a dimensional weight calculation.

result.actual_weight       # Total actual weight in grams
result.dimensional_weight  # Calculated dimensional weight
result.chargeable_weight   # max(actual, dimensional)
result.is_dimensional_used # True if dimensional > actual
result.weight_difference   # chargeable - actual

BoxSelectionResult

Result of box selection with weight calculation.

result.box                    # Selected Box
result.weight                 # WeightResult
result.total_products_volume  # Sum of product volumes
result.utilization_percentage # (products_volume / box_volume) × 100
result.to_dict()              # Convert to dictionary for JSON

Classes

DimCalc

Core dimensional weight calculator.

calc = DimCalc(dimensional_factor=5.0)

# Calculate dimensional weight only
dim_weight = calc.calculate_dimensional_weight(dimensions, quantity=1)

# Calculate chargeable weight (max of actual and dimensional)
result = calc.calculate_chargeable_weight(
    actual_weight=500,
    dimensions=dims,
    quantity=1
)

# Calculate for multiple products
result = calc.calculate_for_products(products)

BoxSelector

Selects optimal shipping box for products.

selector = BoxSelector(
    boxes=boxes,                      # List of available Box objects
    volume_buffer_percentage=20.0,    # Extra space for packing (default: 20%)
    calculator=DimCalc()              # Optional custom calculator
)

result = selector.select_box(products)  # Returns BoxSelectionResult or None
can_fit = selector.can_fit(products)    # Returns bool

WeightDistributor

Distributes chargeable weight across products.

# Proportional distribution (based on actual weight)
distributed = WeightDistributor.distribute(products, box_result)

# Even distribution (equal per unit)
distributed = WeightDistributor.distribute_evenly(products, total_weight)

Dimensional Factors

The dimensional factor (DIM factor) converts volume to weight. Common values:

Carrier Factor Unit Conversion
Iran Post 5.0 cm³ → grams
DHL 5000.0 cm³ → kg

Formula: dimensional_weight = volume / dimensional_factor

Presets

The library includes example presets you can use as reference:

from dimcalc.presets import IRAN_POST_BOXES, DIMENSIONAL_FACTORS, get_iran_post_selector

# Example box configurations
print(IRAN_POST_BOXES)  # List of 8 standard Iran Post boxes

# Common DIM factors
print(DIMENSIONAL_FACTORS)  # {"iran_post": 5.0, "dhl": 5000.0, ...}

# Pre-configured selector for Iran Post
selector = get_iran_post_selector()

Note: Box sizes vary by region and carrier. Create your own box list based on your specific requirements:

# Define your own boxes
MY_BOXES = [
    Box(id="xs", length=15, width=10, height=10, name="Extra Small"),
    Box(id="s", length=20, width=15, height=10, name="Small"),
    Box(id="m", length=30, width=20, height=15, name="Medium"),
    Box(id="l", length=40, width=30, height=20, name="Large"),
]

selector = BoxSelector(boxes=MY_BOXES)

JSON Serialization

Results can be easily serialized for API responses:

result = selector.select_box(products)
data = result.to_dict()

# Returns:
{
    "box_id": "medium",
    "box_name": "Medium Box",
    "box_dimensions": {
        "length_cm": 30,
        "width_cm": 20,
        "height_cm": 15,
        "volume_cm3": 9000
    },
    "weight": {
        "actual_weight_g": 1300,
        "dimensional_weight_g": 1800,
        "chargeable_weight_g": 1800,
        "is_dimensional_used": True
    },
    "packing_info": {
        "total_products_volume_cm3": 2900,
        "utilization_percentage": 32.22
    }
}

Pydantic models also support .model_dump() for serialization:

dims = Dimensions(length=30, width=20, height=10)
dims.model_dump()  # {"length": 30, "width": 20, "height": 10, "volume": 6000, "max_dimension": 30}

License

MIT

Metadata

Release files for dimcalc 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dimcalc 1.0.0
File Size Uploaded
dimcalc-1.0.0.tar.gz 12.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dimcalc 1.0.0
File Interpreter ABI Platform
dimcalc-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.3 kB

Release files / dimcalc-1.0.0.tar.gz

Download URL dimcalc-1.0.0.tar.gz
Size 12.6 kB
Tags Source
SHA-256 checksum
How to use checksums
98b23afa611186208811c46180f0fe55f336333757ff198a7273d9578a5fa584
BLAKE2b-256 checksum
How to use checksums
5c30adad28737c533ab76ffc681e693ae69cc25d0b5539a739888508862ecc4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / dimcalc-1.0.0-py3-none-any.whl

Download URL dimcalc-1.0.0-py3-none-any.whl
Size 11.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3b510478ba23e05aea5c3a8d78a7647b3d43787ebe316b454f4c50447af3c04b
BLAKE2b-256 checksum
How to use checksums
02e7facd17859fc2a7302dee6c30d841d007bb952c7811cd73b6a774a5285e84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page