📐 MecaPy Standard Types Guide
Complete reference for writing type-safe function parameters
Overview
Section intitulée « Overview »MecaPy enforces a restricted set of well-defined types for function parameters to ensure:
- Consistent documentation across all packages
- Robust validation at the API level
- Predictable UI generation for function inputs
- Full JSON Schema compatibility
Supported Standard Types
Section intitulée « Supported Standard Types »| Type | JSON Schema | Use Case | Example |
|---|---|---|---|
int | integer | Countable quantities, iterations | nb_bolts: int |
int (≥0) | integer + minimum: 0 | Non-negative counts | quantity: Annotated[int, Field(ge=0)] |
float | number | Measurements, forces, dimensions | force: float |
float (≥0) | number + minimum: 0 | Physical quantities (≥0) | diameter: Annotated[float, Field(ge=0)] |
str | string | Text, designations, labels | designation: str |
Literal[...] | string + enum | Fixed choice list | material: Literal["S235", "S355"] |
list[T] | array | Collections of values | forces: list[float] |
Type 1: Integer
Section intitulée « Type 1: Integer »Basic Integer
Section intitulée « Basic Integer »def calculate( nb_iterations: int) -> dict: """ Run iterative calculation.
Parameters ---------- nb_iterations : int Number of iterations to perform """ ...Generated JSON Schema:
{ "nb_iterations": { "type": "integer" }}Constrained Integer
Section intitulée « Constrained Integer »from typing import Annotatedfrom pydantic import Field
def calculate( nb_iterations: Annotated[int, Field( description="Number of iterations to perform", ge=1, # Greater or equal (minimum) le=1000, # Less or equal (maximum) examples=[10, 50, 100] )]) -> dict: """ Run iterative calculation.
Parameters ---------- nb_iterations : int Number of iterations (1-1000) """ ...Generated JSON Schema:
{ "nb_iterations": { "type": "integer", "description": "Number of iterations to perform", "minimum": 1, "maximum": 1000, "examples": [10, 50, 100] }}Integer with Default Value
Section intitulée « Integer with Default Value »def calculate( nb_iterations: Annotated[int, Field(ge=1, le=1000)] = 10) -> dict: """Calculate with default iterations.""" ...JSON Schema:
{ "nb_iterations": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 10 }}Type 2: Non-negative Integer
Section intitulée « Type 2: Non-negative Integer »For quantities that cannot be negative (counts, indices, etc.)
def calculate_bolts( nb_bolts: Annotated[int, Field( description="Number of bolts in assembly", ge=0, # Non-negative le=100, examples=[4, 8, 12] )]) -> dict: """ Calculate bolted assembly.
Parameters ---------- nb_bolts : int Number of bolts (0-100) """ ...JSON Schema:
{ "nb_bolts": { "type": "integer", "description": "Number of bolts in assembly", "minimum": 0, "maximum": 100, "examples": [4, 8, 12] }}Type 3: Float (Decimal Number)
Section intitulée « Type 3: Float (Decimal Number) »Basic Float
Section intitulée « Basic Float »def calculate_stress( force: float) -> dict: """ Calculate stress.
Parameters ---------- force : float Applied force in Newton """ ...JSON Schema:
{ "force": { "type": "number" }}Constrained Float
Section intitulée « Constrained Float »def calculate_stress( force: Annotated[float, Field( description="Applied force in Newton", ge=0, # Non-negative le=500000, # Maximum 500 kN examples=[1000, 5000, 10000] )]) -> dict: """ Calculate stress from applied force.
Parameters ---------- force : float Applied force in Newton (0-500,000 N) """ ...JSON Schema:
{ "force": { "type": "number", "description": "Applied force in Newton", "minimum": 0, "maximum": 500000, "examples": [1000, 5000, 10000] }}Float with Strict Bounds
Section intitulée « Float with Strict Bounds »def calculate( temperature: Annotated[float, Field( description="Temperature in Celsius", gt=-273.15, # Greater than (exclusive) lt=1000, # Less than (exclusive) examples=[20, 100, 500] )]) -> dict: """ Temperature-dependent calculation.
Parameters ---------- temperature : float Temperature in °C (above absolute zero, below 1000°C) """ ...JSON Schema:
{ "temperature": { "type": "number", "description": "Temperature in Celsius", "exclusiveMinimum": -273.15, "exclusiveMaximum": 1000, "examples": [20, 100, 500] }}Type 4: String
Section intitulée « Type 4: String »Basic String
Section intitulée « Basic String »def create_element( designation: str) -> dict: """ Create structural element.
Parameters ---------- designation : str Element designation (e.g., HEA200, IPE300) """ ...JSON Schema:
{ "designation": { "type": "string" }}Constrained String
Section intitulée « Constrained String »def create_element( designation: Annotated[str, Field( description="Element designation (e.g., HEA200, IPE300)", min_length=1, max_length=50, examples=["HEA200", "IPE300", "M12"] )]) -> dict: """ Create structural element.
Parameters ---------- designation : str Element designation (1-50 characters) """ ...JSON Schema:
{ "designation": { "type": "string", "description": "Element designation (e.g., HEA200, IPE300)", "minLength": 1, "maxLength": 50, "examples": ["HEA200", "IPE300", "M12"] }}String with Pattern (Use sparingly - prefer Literal)
Section intitulée « String with Pattern (Use sparingly - prefer Literal) »def create_bolt( designation: Annotated[str, Field( description="Bolt designation in M format", pattern="^M[0-9]{1,3}$", examples=["M8", "M12", "M16", "M20"] )]) -> dict: """ Create bolt from designation.
Parameters ---------- designation : str Metric designation (M8, M12, etc.) """ ...JSON Schema:
{ "designation": { "type": "string", "description": "Bolt designation in M format", "pattern": "^M[0-9]{1,3}$", "examples": ["M8", "M12", "M16", "M20"] }}⚠️ Note: Prefer Literal over pattern when choices are fixed.
Type 5: Literal (Enum - Fixed Choices)
Section intitulée « Type 5: Literal (Enum - Fixed Choices) »Basic Literal
Section intitulée « Basic Literal »from typing import Literal
def calculate_assembly( material: Literal["S235", "S355", "S460"]) -> dict: """ Calculate assembly with steel material.
Parameters ---------- material : {"S235", "S355", "S460"} Steel grade according to EN 10025 """ ...JSON Schema:
{ "material": { "type": "string", "enum": ["S235", "S355", "S460"] }}Literal with Description and Default
Section intitulée « Literal with Description and Default »def calculate_assembly( material: Annotated[Literal["S235", "S355", "S460"], Field( description="Steel grade according to EN 10025" )] = "S235", bolt_class: Literal["4.6", "5.6", "8.8", "10.9"] = "8.8") -> dict: """ Calculate bolted assembly.
Parameters ---------- material : {"S235", "S355", "S460"} Steel grade (default: S235) bolt_class : {"4.6", "5.6", "8.8", "10.9"} Bolt property class (default: 8.8) """ ...JSON Schema:
{ "material": { "type": "string", "description": "Steel grade according to EN 10025", "enum": ["S235", "S355", "S460"], "default": "S235" }, "bolt_class": { "type": "string", "enum": ["4.6", "5.6", "8.8", "10.9"], "default": "8.8" }}Boolean as Literal (Recommended)
Section intitulée « Boolean as Literal (Recommended) »def calculate( preloaded: Literal["yes", "no"] = "yes") -> dict: """ Calculate assembly.
Parameters ---------- preloaded : {"yes", "no"} Whether assembly is preloaded """ ...💡 Tip: Use Literal["yes", "no"] instead of bool for clearer UI representation.
Type 6: Array (List)
Section intitulée « Type 6: Array (List) »Basic Array
Section intitulée « Basic Array »def calculate( forces: list[float]) -> dict: """ Calculate resultant force.
Parameters ---------- forces : list of float List of forces in Newton """ ...JSON Schema:
{ "forces": { "type": "array", "items": { "type": "number" } }}Constrained Array
Section intitulée « Constrained Array »def calculate( forces: Annotated[list[float], Field( description="List of forces in Newton", min_length=1, # At least 1 element max_length=10, # Maximum 10 elements )]) -> dict: """ Calculate resultant force.
Parameters ---------- forces : list of float List of forces (1-10 values) """ ...JSON Schema:
{ "forces": { "type": "array", "description": "List of forces in Newton", "items": { "type": "number" }, "minItems": 1, "maxItems": 10 }}Array with Default Value
Section intitulée « Array with Default Value »def calculate( coefficients: list[float] = [1.0, 1.5, 2.0]) -> dict: """ Calculate with safety coefficients.
Parameters ---------- coefficients : list of float Safety coefficients (default: [1.0, 1.5, 2.0]) """ ...JSON Schema:
{ "coefficients": { "type": "array", "items": { "type": "number" }, "default": [1.0, 1.5, 2.0] }}Array of Integers
Section intitulée « Array of Integers »def calculate( node_ids: Annotated[list[int], Field( description="List of node IDs", min_length=2, max_length=100 )]) -> dict: """ Calculate from mesh nodes.
Parameters ---------- node_ids : list of int Mesh node identifiers (2-100 nodes) """ ...JSON Schema:
{ "node_ids": { "type": "array", "description": "List of node IDs", "items": { "type": "integer" }, "minItems": 2, "maxItems": 100 }}Complete Real-World Example
Section intitulée « Complete Real-World Example »from typing import Annotated, Literalfrom pydantic import Field
def calculate_bolted_connection( # Non-negative float with bounds diameter: Annotated[float, Field( description="Nominal bolt diameter in mm", ge=6, le=100, examples=[8, 10, 12, 16, 20, 24] )],
# Literal (enum) for material material: Annotated[Literal["S235", "S355", "S460"], Field( description="Steel grade according to EN 10025" )],
# Literal for bolt class bolt_class: Literal["4.6", "5.6", "8.8", "10.9"] = "8.8",
# Non-negative integer nb_bolts: Annotated[int, Field( description="Number of bolts in connection", ge=1, le=100, examples=[4, 6, 8, 12] )],
# Array of forces forces: Annotated[list[float], Field( description="Applied forces in Newton", min_length=1, max_length=10 )],
# Boolean as Literal preloaded: Literal["yes", "no"] = "yes"
) -> dict: """ Calculate bolted connection according to Eurocode 3.
Parameters ---------- diameter : float Nominal bolt diameter in mm (6-100 mm) material : {"S235", "S355", "S460"} Steel grade according to EN 10025 bolt_class : {"4.6", "5.6", "8.8", "10.9"} Bolt property class (default: 8.8) nb_bolts : int Number of bolts (1-100) forces : list of float Applied forces in Newton (1-10 values) preloaded : {"yes", "no"} Whether connection is preloaded (default: yes)
Returns ------- dict Calculation results with resistance and utilization """ ...Generated JSON Schema:
{ "type": "object", "properties": { "diameter": { "type": "number", "description": "Nominal bolt diameter in mm", "minimum": 6, "maximum": 100, "examples": [8, 10, 12, 16, 20, 24] }, "material": { "type": "string", "description": "Steel grade according to EN 10025", "enum": ["S235", "S355", "S460"] }, "bolt_class": { "type": "string", "enum": ["4.6", "5.6", "8.8", "10.9"], "default": "8.8" }, "nb_bolts": { "type": "integer", "description": "Number of bolts in connection", "minimum": 1, "maximum": 100, "examples": [4, 6, 8, 12] }, "forces": { "type": "array", "description": "Applied forces in Newton", "items": {"type": "number"}, "minItems": 1, "maxItems": 10 }, "preloaded": { "type": "string", "enum": ["yes", "no"], "default": "yes" } }, "required": ["diameter", "material", "nb_bolts", "forces"]}Anti-Patterns (What NOT to Do)
Section intitulée « Anti-Patterns (What NOT to Do) »❌ Complex Nested Types
Section intitulée « ❌ Complex Nested Types »# ❌ BAD: Nested dict with tuplesdef calculate( config: dict[str, list[tuple[int, float]]]) -> dict: ...Problem: Cannot be reliably introspected and validated.
✅ Solution: Flatten to simple types
def calculate( node_ids: list[int], node_values: list[float]) -> dict: ...❌ Pattern When Literal Exists
Section intitulée « ❌ Pattern When Literal Exists »# ❌ BAD: Regex for fixed choicesmaterial: Annotated[str, Field( pattern="^(S235|S355|S460)$")]✅ Solution: Use Literal
material: Literal["S235", "S355", "S460"]❌ Boolean Instead of Literal
Section intitulée « ❌ Boolean Instead of Literal »# ❌ ACCEPTABLE but not idealpreloaded: bool = True✅ Better: Explicit choices
preloaded: Literal["yes", "no"] = "yes"❌ Missing Constraints
Section intitulée « ❌ Missing Constraints »# ❌ BAD: No validationdiameter: float✅ Solution: Add sensible bounds
diameter: Annotated[float, Field( description="Diameter in mm", ge=0, le=1000)]Validation Checklist
Section intitulée « Validation Checklist »Before publishing a package, verify:
- All parameters use standard types (int, float, str, Literal, list)
- Numeric constraints are coherent (ge ≤ le, gt < lt)
- Descriptions are clear and concise
- Examples cover typical use cases
- Default values are sensible
- No complex types (nested dict, tuple, Union, etc.)
- Literal is preferred over regex patterns
- Physical units are documented in descriptions
- Bounds reflect realistic engineering values
- NumPy docstrings match type annotations
References
Section intitulée « References »- MANIFEST_FORMAT.md - Full manifest specification
- Pydantic Field Documentation
- JSON Schema Specification
- NumPy Docstring Standard
Keep it simple. Use standard types. Document clearly. Validate properly. 🚀