| Name | mixam-sdk JSON |
| Version |
0.1.10
JSON |
| download |
| home_page | None |
| Summary | Mixam Python SDK: ItemSpecification Core Models & Enums. KeyBuilder & KeyParser For Working With Universal Keys |
| upload_time | 2025-10-07 09:44:26 |
| maintainer | None |
| docs_url | None |
| author | Mixam |
| requires_python | <4.0,>=3.12 |
| license | None |
| keywords |
mixam
sdk
printing
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# Mixam Python SDK
Mixam SDK is a lightweight Python library that helps you build, validate, serialize, and parse print Item Specifications used by Mixam. It provides:
- Core data models and enums to represent product specifications (components, substrates, bindings, sizes, etc.).
- A Universal Key system to serialize an ItemSpecification to a compact string and parse it back reliably.
## Installation
- Via pip:
```bash
pip install mixam-sdk
```
- Via Poetry:
```bash
poetry add mixam-sdk
```
Python 3.12+ is required (see `pyproject.toml`).
## Developers
- Run tests:
```bash
pytest -q
```
- Local install for development:
```bash
poetry install
poetry run pytest -q
```
See the Development section below for more details.
## Quick Start
Below are minimal examples showing how to work with Item Specifications and the Universal Key.
### Create an ItemSpecification and build a Universal Key
```python
from mixam_sdk.item_specification.models.item_specification import ItemSpecification
from mixam_sdk.item_specification.enums.product import Product
from mixam_sdk.item_specification.models.flat_component import FlatComponent
from mixam_sdk.item_specification.enums.component_type import ComponentType
from mixam_sdk.universal_key.models.key_builder import KeyBuilder
# Build a simple spec with one flat component
item = ItemSpecification()
item.copies = 250
item.product = Product.POSTERS
# Create a simple flat component
comp = FlatComponent()
comp.component_type = ComponentType.FLAT
# ... populate additional fields supported by FlatComponent as needed ...
item.components.append(comp)
# Build a Universal Key string
key = KeyBuilder().build(item)
print(key)
```
### Parse a Universal Key back into an ItemSpecification
```python
from mixam_sdk.universal_key.models.key_parser import KeyParser
parser = KeyParser()
# Provide a Universal Key string (from earlier build step or an external source)
some_key = "250~10-ft{...}"
parsed = parser.parse(some_key)
print(parsed.copies)
print(parsed.product)
print([c.component_type for c in parsed.components])
```
If the key does not match the expected format, `KeyParser.parse` raises a `ValueError` or `RuntimeError` indicating the issue.
## What is a Universal Key?
A Universal Key is a compact, validated string representation of an `ItemSpecification`.
- Format (high level):
- `copies~productId-<component>{<memberTokens>}-<component>{...}`
- Example: `250~10-ft{...}-bd{...}`
- Keys are validated using a strict regex to ensure correctness before parsing.
The SDK provides:
- `KeyBuilder` to generate keys from `ItemSpecification` objects.
- `KeyParser` to parse keys back into `ItemSpecification` objects.
## Main Concepts
- Enums: Found under `mixam_sdk/item_specification/enums`, they define allowed values for products, sizes, colours, laminations, bindings, etc.
- Models: Under `mixam_sdk/item_specification/models`, they represent components such as flat, folded, cover, bound components, and more, as well as the root `ItemSpecification`.
- Interfaces/Support: Internal helpers for ordering components and mapping model fields to the Universal Key token format.
Explore the `tests/` folder for concrete usage patterns and expected behaviours:
- `tests/test_universal_key.py`
- `tests/test_item_specification_deserialization.py`
## Product Metadata and Validation
This SDK models Mixam Product Metadata and provides a validation service to check that a given `ItemSpecification` complies with that metadata.
Important scope notes:
- The validator service is the recommended way to validate a full ItemSpecification. Use `ProductItemSpecificationValidator` for end-to-end validation.
- For advanced implementations, you may validate only a specific component type using its corresponding component validator (component-based validation). See the section below for details.
- The SDK itself does not fetch product metadata; you must retrieve it from the Mixam Public API and pass it to the SDK.
- The SDK focuses on modelling the metadata objects and validating specifications against them.
Obtaining Product Metadata (Mixam Public API):
- Documentation: https://mixam.co.uk/documentation/api/public#openapi
- Endpoint to get product metadata for a specific product and sub-product (provide `productId`, `subProductId`, and `quoteType`, usually `QUOTE`):
- Example: https://mixam.co.uk/api/public/products/metadata/1/0?quoteType=QUOTE
What is Product Metadata?
- A structured definition of the options and constraints for a specific product (allowed components, sizes, substrates, laminations, page ranges, etc.).
- Represented by `mixam_sdk.metadata.product.models.product_metadata.ProductMetadata` (a Pydantic model).
Validation at a glance:
- You validate an `ItemSpecification` against a `ProductMetadata` using `ProductItemSpecificationValidator`.
- Validation returns a `ValidationResult` containing a list of violations (errors) and optionally warnings.
- Validation is not fail-fast; it accumulates all violations so you can report everything in one pass.
- Each violation includes a machine-readable `code`, a human `message`, a `path` to the offending field/component, and optional `allowed` or other context.
End-to-end example (fetch metadata, build spec in code, validate via service):
```python
import json
from urllib.request import urlopen
from mixam_sdk.item_specification.models.item_specification import ItemSpecification
from mixam_sdk.item_specification.models.flat_component import FlatComponent
from mixam_sdk.item_specification.enums.component_type import ComponentType
from mixam_sdk.metadata.product.models.product_metadata import ProductMetadata
from mixam_sdk.metadata.product.services.validator import ProductItemSpecificationValidator
# 1) Fetch Product Metadata from Mixam Public API (replace IDs as needed)
product_id = 1
sub_product_id = 0
quote_type = "QUOTE"
url = f"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}"
with urlopen(url, timeout=20) as resp:
pm_json = resp.read().decode("utf-8")
pm = ProductMetadata.model_validate_json(pm_json)
# 2) Build an ItemSpecification in code (example: simple flat/poster-style component)
spec = ItemSpecification()
spec.copies = 100
comp = FlatComponent()
comp.component_type = ComponentType.FLAT
# Populate additional fields that your product requires (size, substrate, colours, etc.)
# e.g. comp.standard_size = ... ; comp.substrate = ... ; comp.colours = ...
spec.components.append(comp)
# 3) Validate via the service (the only supported entry point)
validator = ProductItemSpecificationValidator()
result = validator.validate(pm, spec)
# 4) Inspect result
if result.is_valid():
print("Spec is valid for this product")
else:
for err in result.errors:
print(f"{err.path}: {err.code} - {err.message}")
if err.allowed:
print(f" allowed: {err.allowed}")
```
Notes:
- Do not call `metadata.validate(spec)` directly; use `ProductItemSpecificationValidator`.
- Ensure the ItemSpecification fields you set correspond to options allowed by the fetched metadata.
Key classes:
- ProductMetadata: Pydantic model for the product's rules and options.
- ProductItemSpecificationValidator: Service that validates an `ItemSpecification` against `ProductMetadata`.
- ValidationResult and ValidationMessage: Returned by validation; contains `errors`, `warnings`, and helpers like `.is_valid()` and `.humanize()`.
See also:
- Component validators under `mixam_sdk/metadata/product/models/validators/` for component-specific rules (e.g., cover, bound, envelope).
- Tests that exercise validation: `tests/test_product_item_spec_validation.py`, product-specific tests like posters/booklets, etc.
### Example: Validate a 100 A5 Portrait Stapled Booklet (32 pages)
The following JSON spec (simplified) describes what we want to validate:
- 100 Booklets
- Size: A5 (148 mm x 210 mm) - Portrait
- Stapled, Full-colour printing, 32 pages, 130gsm Silk
- Cover: Full-colour printing (front and back), 250gsm Silk
And here is the equivalent ItemSpecification built in code and validated via the service:
```python
from urllib.request import urlopen
from mixam_sdk.item_specification.models.item_specification import ItemSpecification
from mixam_sdk.item_specification.enums.product import Product
from mixam_sdk.item_specification.models.bound_component import BoundComponent
from mixam_sdk.item_specification.models.cover_component import CoverComponent
from mixam_sdk.item_specification.models.substrate import Substrate
from mixam_sdk.item_specification.models.binding import Binding
from mixam_sdk.item_specification.enums.orientation import Orientation
from mixam_sdk.item_specification.enums.colours import Colours
from mixam_sdk.item_specification.enums.standard_size import StandardSize
from mixam_sdk.item_specification.enums.lamination import Lamination
from mixam_sdk.item_specification.enums.ribbon_colour import RibbonColour
from mixam_sdk.item_specification.enums.binding_type import BindingType
from mixam_sdk.item_specification.enums.binding_edge import BindingEdge
from mixam_sdk.item_specification.enums.substrate_design import SubstrateDesign
from mixam_sdk.metadata.product.models.product_metadata import ProductMetadata
from mixam_sdk.metadata.product.services.validator import ProductItemSpecificationValidator
# 1) Fetch metadata for brochures (replace IDs for your locale/product if needed)
product_id = 1
sub_product_id = 0
quote_type = "QUOTE"
url = f"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}"
with urlopen(url, timeout=20) as resp:
pm_json = resp.read().decode("utf-8")
pm = ProductMetadata.model_validate_json(pm_json)
# 2) Build the ItemSpecification matching the provided spec
spec = ItemSpecification()
spec.copies = 100
spec.product = Product.BROCHURES
# Primary content (text) block: BOUND component
inner = BoundComponent()
inner.format = 5 # A5
inner.orientation = Orientation.PORTRAIT
inner.colours = Colours.PROCESS
inner.substrate = Substrate(typeId=1, weightId=3, colourId=0, design=SubstrateDesign.NONE)
inner.pages = 32
inner.lamination = Lamination.NONE
inner.binding = Binding(type=BindingType.STAPLED, sewn=False, edge=BindingEdge.LEFT_RIGHT)
inner.ribbon_colour = RibbonColour.NONE
# Cover block: COVER component (front and back)
cover = CoverComponent()
cover.format = 5 # A5
cover.orientation = Orientation.PORTRAIT
cover.colours = Colours.PROCESS
cover.substrate = Substrate(typeId=1, weightId=7, colourId=0, design=SubstrateDesign.NONE)
cover.lamination = Lamination.NONE
cover.back_colours = Colours.PROCESS
cover.back_lamination = Lamination.NONE
spec.components = [inner, cover]
# 3) Validate via the service
validator = ProductItemSpecificationValidator()
result = validator.validate(pm, spec)
if result.is_valid():
print("Spec is valid for this product")
else:
for err in result.errors:
print(f"{err.path}: {err.code} - {err.message}")
if err.allowed:
print(f" allowed: {err.allowed}")
```
Notes:
- Substrate IDs (typeId/weightId/colourId) must match what the fetched Product Metadata allows for the chosen product and sub-product.
## Error Handling
- `KeyParser.parse(key)` validates input and raises a `ValueError` for invalid format and a `RuntimeError` for parsing failures.
- When building keys, ensure your components are populated with required fields; otherwise the builder may not emit expected tokens.
## Development
- Run tests:
```bash
pytest -q
```
- Local install for development:
```bash
poetry install
poetry run pytest -q
```
## Versioning
The package follows semantic versioning where possible. See `pyproject.toml` for the current version.
## License
Copyright (c) Mixam.
See the repository for license terms or contact developer@mixam.com.
## Examples (from tests)
Below are full examples taken directly from the test suite to illustrate the exact formats.
- Universal Key example (Booklet):
```
10~1-bd{4bt-5c-4f-200p-1st-3sw}-cr{5c-5c+-4f-4l-1st-7sw}
```
- Matching ItemSpecification JSON example (as used in tests):
```json
{
"itemSpecification": {
"copies": 10,
"product": "BROCHURES",
"components": [
{
"componentType": "BOUND",
"format": 4,
"standardSize": "NONE",
"orientation": "PORTRAIT",
"colours": "PROCESS",
"substrate": {
"typeId": 1,
"weightId": 3,
"colourId": 0
},
"pages": 200,
"lamination": "NONE",
"binding": {
"type": "PUR"
}
},
{
"componentType": "COVER",
"format": 4,
"standardSize": "NONE",
"orientation": "PORTRAIT",
"colours": "PROCESS",
"substrate": {
"typeId": 1,
"weightId": 7,
"colourId": 0
},
"lamination": "GLOSS",
"backColours": "PROCESS",
"backLamination": "NONE"
}
]
}
}
```
## Links
- Source: https://github.com/mixam-platform/mixam-python-sdk
- Mixam: https://mixam.com
## Component-based validation (advanced)
### Validate just Cover components with the Cover validator (component-only)
While it is recommended to use the validator service to validate the entire Item Specification, the metadata validation system is component-based under the hood. You can shortcut the flow and validate only a specific component type using its corresponding component validator. This can be useful when composing a spec in a component-by-component manner (e.g., with an AI tool) and you only want to validate the component you just changed.
Below is a fully self-contained example that validates only COVER components using the CoverComponentValidator:
```python
from urllib.request import urlopen
from mixam_sdk.item_specification.models.item_specification import ItemSpecification
from mixam_sdk.item_specification.models.cover_component import CoverComponent
from mixam_sdk.item_specification.models.substrate import Substrate
from mixam_sdk.item_specification.enums.component_type import ComponentType
from mixam_sdk.item_specification.enums.colours import Colours
from mixam_sdk.item_specification.enums.orientation import Orientation
from mixam_sdk.item_specification.enums.standard_size import StandardSize
from mixam_sdk.item_specification.enums.substrate_design import SubstrateDesign
from mixam_sdk.item_specification.enums.product import Product
from mixam_sdk.metadata.product.models.product_metadata import ProductMetadata
from mixam_sdk.metadata.product.models.validators.cover import CoverComponentValidator
from mixam_sdk.metadata.product.services.validation_result import ValidationResult
# 1) Fetch Product Metadata for a brochures-like product (adjust IDs for your target product)
product_id = 1
sub_product_id = 0
quote_type = "QUOTE"
url = f"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}"
with urlopen(url, timeout=20) as resp:
pm_json = resp.read().decode("utf-8")
pm = ProductMetadata.model_validate_json(pm_json)
# 2) Build an ItemSpecification with a COVER component (minimal example)
spec = ItemSpecification()
spec.copies = 100
spec.product = Product.BROCHURES
cover = CoverComponent()
cover.format = 5
cover.orientation = Orientation.PORTRAIT
cover.colours = Colours.PROCESS
cover.substrate = Substrate(typeId=1, weightId=7, colourId=0, design=SubstrateDesign.NONE)
# Optionally set back side settings if printing both sides
cover.back_colours = Colours.PROCESS
spec.components.append(cover)
# 3) Validate only the COVER components using the specific component validator
cover_validator = CoverComponentValidator()
partial_result = ValidationResult()
for idx, comp in enumerate(spec.components):
if comp.component_type == ComponentType.COVER:
base_path = f"components[{idx}]"
cover_validator.validate(pm, spec, comp, partial_result, base_path)
# 4) Inspect results from validating only the cover components
if partial_result.is_valid():
print("All cover components are valid")
else:
for err in partial_result.errors:
print(f"{err.path}: {err.code} - {err.message}")
if err.allowed:
print(f" allowed: {err.allowed}")
```
Notes and caveats:
- Prefer ProductItemSpecificationValidator for full validation because it also enforces top-level requirements (e.g., component counts, cross-component constraints) and runs primary-component rules.
- Component-only validation runs the base checks plus cover-specific rules implemented in CoverComponentValidator. It does not validate other component types present in the spec.
- The same pattern works for other component validators, e.g., DustJacketComponentValidator for dust jackets.
Raw data
{
"_id": null,
"home_page": null,
"name": "mixam-sdk",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.12",
"maintainer_email": null,
"keywords": "mixam, sdk, printing",
"author": "Mixam",
"author_email": "developer@mixam.com",
"download_url": "https://files.pythonhosted.org/packages/25/26/81ecd0766c2914bf5fe07134b76e5eb8f67e9a689ded119ce42c7ed8ca07/mixam_sdk-0.1.10.tar.gz",
"platform": null,
"description": "# Mixam Python SDK\n\nMixam SDK is a lightweight Python library that helps you build, validate, serialize, and parse print Item Specifications used by Mixam. It provides:\n\n- Core data models and enums to represent product specifications (components, substrates, bindings, sizes, etc.).\n- A Universal Key system to serialize an ItemSpecification to a compact string and parse it back reliably.\n\n## Installation\n\n- Via pip:\n\n```bash\npip install mixam-sdk\n```\n\n- Via Poetry:\n\n```bash\npoetry add mixam-sdk\n```\n\nPython 3.12+ is required (see `pyproject.toml`).\n\n## Developers\n\n- Run tests:\n\n```bash\npytest -q\n```\n\n- Local install for development:\n\n```bash\npoetry install\npoetry run pytest -q\n```\n\nSee the Development section below for more details.\n\n## Quick Start\n\nBelow are minimal examples showing how to work with Item Specifications and the Universal Key.\n\n### Create an ItemSpecification and build a Universal Key\n\n```python\nfrom mixam_sdk.item_specification.models.item_specification import ItemSpecification\nfrom mixam_sdk.item_specification.enums.product import Product\nfrom mixam_sdk.item_specification.models.flat_component import FlatComponent\nfrom mixam_sdk.item_specification.enums.component_type import ComponentType\nfrom mixam_sdk.universal_key.models.key_builder import KeyBuilder\n\n# Build a simple spec with one flat component\nitem = ItemSpecification()\nitem.copies = 250\nitem.product = Product.POSTERS\n\n# Create a simple flat component\ncomp = FlatComponent()\ncomp.component_type = ComponentType.FLAT\n# ... populate additional fields supported by FlatComponent as needed ...\n\nitem.components.append(comp)\n\n# Build a Universal Key string\nkey = KeyBuilder().build(item)\nprint(key)\n```\n\n### Parse a Universal Key back into an ItemSpecification\n\n```python\nfrom mixam_sdk.universal_key.models.key_parser import KeyParser\n\nparser = KeyParser()\n# Provide a Universal Key string (from earlier build step or an external source)\nsome_key = \"250~10-ft{...}\"\nparsed = parser.parse(some_key)\n\nprint(parsed.copies)\nprint(parsed.product)\nprint([c.component_type for c in parsed.components])\n```\n\nIf the key does not match the expected format, `KeyParser.parse` raises a `ValueError` or `RuntimeError` indicating the issue.\n\n## What is a Universal Key?\n\nA Universal Key is a compact, validated string representation of an `ItemSpecification`.\n\n- Format (high level):\n - `copies~productId-<component>{<memberTokens>}-<component>{...}`\n- Example: `250~10-ft{...}-bd{...}`\n- Keys are validated using a strict regex to ensure correctness before parsing.\n\nThe SDK provides:\n\n- `KeyBuilder` to generate keys from `ItemSpecification` objects.\n- `KeyParser` to parse keys back into `ItemSpecification` objects.\n\n## Main Concepts\n\n- Enums: Found under `mixam_sdk/item_specification/enums`, they define allowed values for products, sizes, colours, laminations, bindings, etc.\n- Models: Under `mixam_sdk/item_specification/models`, they represent components such as flat, folded, cover, bound components, and more, as well as the root `ItemSpecification`.\n- Interfaces/Support: Internal helpers for ordering components and mapping model fields to the Universal Key token format.\n\nExplore the `tests/` folder for concrete usage patterns and expected behaviours:\n\n- `tests/test_universal_key.py`\n- `tests/test_item_specification_deserialization.py`\n\n## Product Metadata and Validation\n\nThis SDK models Mixam Product Metadata and provides a validation service to check that a given `ItemSpecification` complies with that metadata.\n\nImportant scope notes:\n- The validator service is the recommended way to validate a full ItemSpecification. Use `ProductItemSpecificationValidator` for end-to-end validation.\n- For advanced implementations, you may validate only a specific component type using its corresponding component validator (component-based validation). See the section below for details.\n- The SDK itself does not fetch product metadata; you must retrieve it from the Mixam Public API and pass it to the SDK.\n- The SDK focuses on modelling the metadata objects and validating specifications against them.\n\nObtaining Product Metadata (Mixam Public API):\n- Documentation: https://mixam.co.uk/documentation/api/public#openapi\n- Endpoint to get product metadata for a specific product and sub-product (provide `productId`, `subProductId`, and `quoteType`, usually `QUOTE`):\n - Example: https://mixam.co.uk/api/public/products/metadata/1/0?quoteType=QUOTE\n\nWhat is Product Metadata?\n- A structured definition of the options and constraints for a specific product (allowed components, sizes, substrates, laminations, page ranges, etc.).\n- Represented by `mixam_sdk.metadata.product.models.product_metadata.ProductMetadata` (a Pydantic model).\n\nValidation at a glance:\n- You validate an `ItemSpecification` against a `ProductMetadata` using `ProductItemSpecificationValidator`.\n- Validation returns a `ValidationResult` containing a list of violations (errors) and optionally warnings.\n- Validation is not fail-fast; it accumulates all violations so you can report everything in one pass.\n- Each violation includes a machine-readable `code`, a human `message`, a `path` to the offending field/component, and optional `allowed` or other context.\n\nEnd-to-end example (fetch metadata, build spec in code, validate via service):\n\n```python\nimport json\nfrom urllib.request import urlopen\n\nfrom mixam_sdk.item_specification.models.item_specification import ItemSpecification\nfrom mixam_sdk.item_specification.models.flat_component import FlatComponent\nfrom mixam_sdk.item_specification.enums.component_type import ComponentType\nfrom mixam_sdk.metadata.product.models.product_metadata import ProductMetadata\nfrom mixam_sdk.metadata.product.services.validator import ProductItemSpecificationValidator\n\n# 1) Fetch Product Metadata from Mixam Public API (replace IDs as needed)\nproduct_id = 1\nsub_product_id = 0\nquote_type = \"QUOTE\"\nurl = f\"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}\"\nwith urlopen(url, timeout=20) as resp:\n pm_json = resp.read().decode(\"utf-8\")\npm = ProductMetadata.model_validate_json(pm_json)\n\n# 2) Build an ItemSpecification in code (example: simple flat/poster-style component)\nspec = ItemSpecification()\nspec.copies = 100\n\ncomp = FlatComponent()\ncomp.component_type = ComponentType.FLAT\n# Populate additional fields that your product requires (size, substrate, colours, etc.)\n# e.g. comp.standard_size = ... ; comp.substrate = ... ; comp.colours = ...\n\nspec.components.append(comp)\n\n# 3) Validate via the service (the only supported entry point)\nvalidator = ProductItemSpecificationValidator()\nresult = validator.validate(pm, spec)\n\n# 4) Inspect result\nif result.is_valid():\n print(\"Spec is valid for this product\")\nelse:\n for err in result.errors:\n print(f\"{err.path}: {err.code} - {err.message}\")\n if err.allowed:\n print(f\" allowed: {err.allowed}\")\n```\n\nNotes:\n- Do not call `metadata.validate(spec)` directly; use `ProductItemSpecificationValidator`.\n- Ensure the ItemSpecification fields you set correspond to options allowed by the fetched metadata.\n\nKey classes:\n- ProductMetadata: Pydantic model for the product's rules and options.\n- ProductItemSpecificationValidator: Service that validates an `ItemSpecification` against `ProductMetadata`.\n- ValidationResult and ValidationMessage: Returned by validation; contains `errors`, `warnings`, and helpers like `.is_valid()` and `.humanize()`.\n\nSee also:\n- Component validators under `mixam_sdk/metadata/product/models/validators/` for component-specific rules (e.g., cover, bound, envelope).\n- Tests that exercise validation: `tests/test_product_item_spec_validation.py`, product-specific tests like posters/booklets, etc.\n\n### Example: Validate a 100 A5 Portrait Stapled Booklet (32 pages)\n\nThe following JSON spec (simplified) describes what we want to validate:\n\n- 100 Booklets\n- Size: A5 (148 mm x 210 mm) - Portrait\n- Stapled, Full-colour printing, 32 pages, 130gsm Silk\n- Cover: Full-colour printing (front and back), 250gsm Silk\n\nAnd here is the equivalent ItemSpecification built in code and validated via the service:\n\n```python\nfrom urllib.request import urlopen\n\nfrom mixam_sdk.item_specification.models.item_specification import ItemSpecification\nfrom mixam_sdk.item_specification.enums.product import Product\nfrom mixam_sdk.item_specification.models.bound_component import BoundComponent\nfrom mixam_sdk.item_specification.models.cover_component import CoverComponent\nfrom mixam_sdk.item_specification.models.substrate import Substrate\nfrom mixam_sdk.item_specification.models.binding import Binding\nfrom mixam_sdk.item_specification.enums.orientation import Orientation\nfrom mixam_sdk.item_specification.enums.colours import Colours\nfrom mixam_sdk.item_specification.enums.standard_size import StandardSize\nfrom mixam_sdk.item_specification.enums.lamination import Lamination\nfrom mixam_sdk.item_specification.enums.ribbon_colour import RibbonColour\nfrom mixam_sdk.item_specification.enums.binding_type import BindingType\nfrom mixam_sdk.item_specification.enums.binding_edge import BindingEdge\nfrom mixam_sdk.item_specification.enums.substrate_design import SubstrateDesign\nfrom mixam_sdk.metadata.product.models.product_metadata import ProductMetadata\nfrom mixam_sdk.metadata.product.services.validator import ProductItemSpecificationValidator\n\n# 1) Fetch metadata for brochures (replace IDs for your locale/product if needed)\nproduct_id = 1\nsub_product_id = 0\nquote_type = \"QUOTE\"\nurl = f\"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}\"\nwith urlopen(url, timeout=20) as resp:\n pm_json = resp.read().decode(\"utf-8\")\npm = ProductMetadata.model_validate_json(pm_json)\n\n# 2) Build the ItemSpecification matching the provided spec\nspec = ItemSpecification()\nspec.copies = 100\nspec.product = Product.BROCHURES\n\n# Primary content (text) block: BOUND component\ninner = BoundComponent()\ninner.format = 5 # A5\ninner.orientation = Orientation.PORTRAIT\ninner.colours = Colours.PROCESS\ninner.substrate = Substrate(typeId=1, weightId=3, colourId=0, design=SubstrateDesign.NONE)\ninner.pages = 32\ninner.lamination = Lamination.NONE\ninner.binding = Binding(type=BindingType.STAPLED, sewn=False, edge=BindingEdge.LEFT_RIGHT)\ninner.ribbon_colour = RibbonColour.NONE\n\n# Cover block: COVER component (front and back)\ncover = CoverComponent()\ncover.format = 5 # A5\ncover.orientation = Orientation.PORTRAIT\ncover.colours = Colours.PROCESS\ncover.substrate = Substrate(typeId=1, weightId=7, colourId=0, design=SubstrateDesign.NONE)\ncover.lamination = Lamination.NONE\ncover.back_colours = Colours.PROCESS\ncover.back_lamination = Lamination.NONE\n\nspec.components = [inner, cover]\n\n# 3) Validate via the service\nvalidator = ProductItemSpecificationValidator()\nresult = validator.validate(pm, spec)\n\nif result.is_valid():\n print(\"Spec is valid for this product\")\nelse:\n for err in result.errors:\n print(f\"{err.path}: {err.code} - {err.message}\")\n if err.allowed:\n print(f\" allowed: {err.allowed}\")\n```\n\nNotes:\n- Substrate IDs (typeId/weightId/colourId) must match what the fetched Product Metadata allows for the chosen product and sub-product.\n\n## Error Handling\n\n- `KeyParser.parse(key)` validates input and raises a `ValueError` for invalid format and a `RuntimeError` for parsing failures.\n- When building keys, ensure your components are populated with required fields; otherwise the builder may not emit expected tokens.\n\n## Development\n\n- Run tests:\n\n```bash\npytest -q\n```\n\n- Local install for development:\n\n```bash\npoetry install\npoetry run pytest -q\n```\n\n## Versioning\n\nThe package follows semantic versioning where possible. See `pyproject.toml` for the current version.\n\n## License\n\nCopyright (c) Mixam.\n\nSee the repository for license terms or contact developer@mixam.com.\n\n## Examples (from tests)\n\nBelow are full examples taken directly from the test suite to illustrate the exact formats.\n\n- Universal Key example (Booklet):\n\n```\n10~1-bd{4bt-5c-4f-200p-1st-3sw}-cr{5c-5c+-4f-4l-1st-7sw}\n```\n\n- Matching ItemSpecification JSON example (as used in tests):\n\n```json\n{\n \"itemSpecification\": {\n \"copies\": 10,\n \"product\": \"BROCHURES\",\n \"components\": [\n {\n \"componentType\": \"BOUND\",\n \"format\": 4,\n \"standardSize\": \"NONE\",\n \"orientation\": \"PORTRAIT\",\n \"colours\": \"PROCESS\",\n \"substrate\": {\n \"typeId\": 1,\n \"weightId\": 3,\n \"colourId\": 0\n },\n \"pages\": 200,\n \"lamination\": \"NONE\",\n \"binding\": {\n \"type\": \"PUR\"\n }\n },\n {\n \"componentType\": \"COVER\",\n \"format\": 4,\n \"standardSize\": \"NONE\",\n \"orientation\": \"PORTRAIT\",\n \"colours\": \"PROCESS\",\n \"substrate\": {\n \"typeId\": 1,\n \"weightId\": 7,\n \"colourId\": 0\n },\n \"lamination\": \"GLOSS\",\n \"backColours\": \"PROCESS\",\n \"backLamination\": \"NONE\"\n }\n ]\n }\n}\n```\n\n## Links\n\n- Source: https://github.com/mixam-platform/mixam-python-sdk\n- Mixam: https://mixam.com\n\n\n## Component-based validation (advanced)\n\n### Validate just Cover components with the Cover validator (component-only)\n\nWhile it is recommended to use the validator service to validate the entire Item Specification, the metadata validation system is component-based under the hood. You can shortcut the flow and validate only a specific component type using its corresponding component validator. This can be useful when composing a spec in a component-by-component manner (e.g., with an AI tool) and you only want to validate the component you just changed.\n\nBelow is a fully self-contained example that validates only COVER components using the CoverComponentValidator:\n\n```python\nfrom urllib.request import urlopen\n\nfrom mixam_sdk.item_specification.models.item_specification import ItemSpecification\nfrom mixam_sdk.item_specification.models.cover_component import CoverComponent\nfrom mixam_sdk.item_specification.models.substrate import Substrate\nfrom mixam_sdk.item_specification.enums.component_type import ComponentType\nfrom mixam_sdk.item_specification.enums.colours import Colours\nfrom mixam_sdk.item_specification.enums.orientation import Orientation\nfrom mixam_sdk.item_specification.enums.standard_size import StandardSize\nfrom mixam_sdk.item_specification.enums.substrate_design import SubstrateDesign\nfrom mixam_sdk.item_specification.enums.product import Product\nfrom mixam_sdk.metadata.product.models.product_metadata import ProductMetadata\nfrom mixam_sdk.metadata.product.models.validators.cover import CoverComponentValidator\nfrom mixam_sdk.metadata.product.services.validation_result import ValidationResult\n\n# 1) Fetch Product Metadata for a brochures-like product (adjust IDs for your target product)\nproduct_id = 1\nsub_product_id = 0\nquote_type = \"QUOTE\"\nurl = f\"https://mixam.co.uk/api/public/products/metadata/{product_id}/{sub_product_id}?quoteType={quote_type}\"\nwith urlopen(url, timeout=20) as resp:\n pm_json = resp.read().decode(\"utf-8\")\npm = ProductMetadata.model_validate_json(pm_json)\n\n# 2) Build an ItemSpecification with a COVER component (minimal example)\nspec = ItemSpecification()\nspec.copies = 100\nspec.product = Product.BROCHURES\n\ncover = CoverComponent()\ncover.format = 5\ncover.orientation = Orientation.PORTRAIT\ncover.colours = Colours.PROCESS\ncover.substrate = Substrate(typeId=1, weightId=7, colourId=0, design=SubstrateDesign.NONE)\n# Optionally set back side settings if printing both sides\ncover.back_colours = Colours.PROCESS\n\nspec.components.append(cover)\n\n# 3) Validate only the COVER components using the specific component validator\ncover_validator = CoverComponentValidator()\npartial_result = ValidationResult()\n\nfor idx, comp in enumerate(spec.components):\n if comp.component_type == ComponentType.COVER:\n base_path = f\"components[{idx}]\"\n cover_validator.validate(pm, spec, comp, partial_result, base_path)\n\n# 4) Inspect results from validating only the cover components\nif partial_result.is_valid():\n print(\"All cover components are valid\")\nelse:\n for err in partial_result.errors:\n print(f\"{err.path}: {err.code} - {err.message}\")\n if err.allowed:\n print(f\" allowed: {err.allowed}\")\n```\n\nNotes and caveats:\n- Prefer ProductItemSpecificationValidator for full validation because it also enforces top-level requirements (e.g., component counts, cross-component constraints) and runs primary-component rules.\n- Component-only validation runs the base checks plus cover-specific rules implemented in CoverComponentValidator. It does not validate other component types present in the spec.\n- The same pattern works for other component validators, e.g., DustJacketComponentValidator for dust jackets.\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Mixam Python SDK: ItemSpecification Core Models & Enums. KeyBuilder & KeyParser For Working With Universal Keys",
"version": "0.1.10",
"project_urls": {
"Homepage": "https://github.com/mixam-platform",
"Repository": "https://github.com/mixam-platform/mixam-python-sdk"
},
"split_keywords": [
"mixam",
" sdk",
" printing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "8cfc4b5949631d3a149a29940f19d59ee93de7d7cf31e3bc0738200dbdc8f716",
"md5": "1a4cd77fa82265ccb2bbaa1becb4f7ca",
"sha256": "2838a918de999d7c4b2fdfea9276aa22f11ee099825aef945b1633c300d2a840"
},
"downloads": -1,
"filename": "mixam_sdk-0.1.10-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1a4cd77fa82265ccb2bbaa1becb4f7ca",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.12",
"size": 106493,
"upload_time": "2025-10-07T09:44:25",
"upload_time_iso_8601": "2025-10-07T09:44:25.452436Z",
"url": "https://files.pythonhosted.org/packages/8c/fc/4b5949631d3a149a29940f19d59ee93de7d7cf31e3bc0738200dbdc8f716/mixam_sdk-0.1.10-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "252681ecd0766c2914bf5fe07134b76e5eb8f67e9a689ded119ce42c7ed8ca07",
"md5": "125db11ba2e20401443aa33c0a43b565",
"sha256": "36eb18bbdcaea3523c60b5c4ca5df62a5018f0d0a0006d1576a8ac61419e8b85"
},
"downloads": -1,
"filename": "mixam_sdk-0.1.10.tar.gz",
"has_sig": false,
"md5_digest": "125db11ba2e20401443aa33c0a43b565",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.12",
"size": 54926,
"upload_time": "2025-10-07T09:44:26",
"upload_time_iso_8601": "2025-10-07T09:44:26.529383Z",
"url": "https://files.pythonhosted.org/packages/25/26/81ecd0766c2914bf5fe07134b76e5eb8f67e9a689ded119ce42c7ed8ca07/mixam_sdk-0.1.10.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-07 09:44:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mixam-platform",
"github_project": "mixam-python-sdk",
"github_not_found": true,
"lcname": "mixam-sdk"
}