Developer CLI for python-sendparcel provider testing and debugging.
Project description
python-sendparcel-cli
Developer CLI for testing and debugging python-sendparcel providers.
Alpha (0.1.0) — API may change between minor releases. Pin your dependency if you use it in production.
Features
- Four commands —
init,providers,check-config, andcreate-labelcover the full provider testing workflow. - Auto-generated config —
initdiscovers all installed providers and generates a TOML config file with required fields from each provider'sconfig_schema. - Provider discovery —
providerslists every installed provider with its slug, display name, confirmation method, supported countries, and configuration status. - Configuration validation —
check-configinspects a specific provider's config fields, showing required/type/value/status with secret masking. - End-to-end label creation —
create-labelcreates a test shipment and downloads the label through the fullShipmentFlowpipeline. - Flexible address input — sender and receiver addresses can be provided via JSON files, inline CLI flags, or a combination of both (flags override file values).
- Provider kwargs passthrough — arbitrary provider-specific parameters via
--kwarg KEY=VALUEflags. - Rich output — formatted tables via Rich for all command output.
- TOML configuration — config stored at
~/.config/sendparcel/config.toml(XDG convention), overridable via--configflag orSENDPARCEL_CONFIGenvironment variable. - Async-first — uses
anyioto run the asyncShipmentFlowfrom the synchronous CLI context.
Installation
uv add python-sendparcel-cli
Or with pip:
pip install python-sendparcel-cli
This installs the sendparcel command. Providers are auto-discovered via the sendparcel.providers entry-point group — install any provider plugin (e.g. python-sendparcel-inpost, python-sendparcel-dpdpl) and it will appear automatically.
Quick Start
Initialize configuration
Generate a config file with empty sections for all installed providers:
sendparcel init
# Config created at /home/user/.config/sendparcel/config.toml
List installed providers
sendparcel providers
Output (example with InPost and DPD installed):
┌─────────────────────────────────────────────────────────────────────┐
│ Installed Providers │
├────────────────┬──────────────────┬────────┬───────────┬───────────┤
│ Slug │ Name │ Method │ Countries │ Config │
├────────────────┼──────────────────┼────────┼───────────┼───────────┤
│ inpost_locker │ InPost Paczkomat │ PUSH │ PL │ OK │
│ inpost_courier │ InPost Kurier │ PUSH │ PL │ --- │
│ dpd_standard │ DPD Kurier │ NONE │ PL │ OK │
└────────────────┴──────────────────┴────────┴───────────┴───────────┘
Check provider configuration
sendparcel check-config inpost_locker
Output shows each config field with its required/type/value/status:
┌──────────────────────────────────────────────────────────────────┐
│ Config: inpost_locker │
├──────────────────┬──────────┬──────┬────────────────┬────────────┤
│ Field │ Required │ Type │ Value │ Status │
├──────────────────┼──────────┼──────┼────────────────┼────────────┤
│ token │ Yes │ str │ *** │ OK │
│ organization_id │ Yes │ int │ 12345 │ OK │
│ sandbox │ No │ bool │ (default: False)│ OK │
└──────────────────┴──────────┴──────┴────────────────┴────────────┘
Secret fields (like token) are masked in the output.
Create a test label
Using JSON address files:
sendparcel create-label inpost_locker \
--sender-file sender.json \
--receiver-file receiver.json \
--weight 2.5 \
--output-dir ./labels \
--kwarg target_point=KRA010
Using inline flags:
sendparcel create-label dpd_standard \
--sender-first-name "Jan" \
--sender-last-name "Nadawca" \
--sender-phone "500100200" \
--sender-email "sender@test.com" \
--sender-street "Testowa" \
--sender-building-number "1" \
--sender-city "Warszawa" \
--sender-postal-code "00-001" \
--sender-country-code "PL" \
--receiver-first-name "Anna" \
--receiver-last-name "Odbiorca" \
--receiver-phone "600200300" \
--receiver-email "receiver@test.com" \
--weight 2.5 \
--output-dir ./labels
Configuration
Config file location
The CLI reads configuration from a TOML file. The location is resolved in this order:
--config <path>flag (highest priority)SENDPARCEL_CONFIGenvironment variable~/.config/sendparcel/config.toml(XDG default)
Config file format
[providers.inpost_locker]
token = "your-shipx-api-token"
organization_id = 12345
sandbox = true
[providers.inpost_courier]
token = "your-shipx-api-token"
organization_id = 12345
sandbox = true
[providers.dpd_standard]
login = "your-dpd-login"
password = "your-dpd-password"
master_fid = 1495
sandbox = true
Each [providers.<slug>] section contains the key-value pairs expected by that provider's config_schema. Run sendparcel init to auto-generate this file with the correct fields for all installed providers.
Commands
sendparcel init
Discovers all installed providers via entry points and generates a config file with empty required fields and default values from each provider's config_schema.
| Option | Type | Default | Description |
|---|---|---|---|
--config |
Path |
~/.config/sendparcel/config.toml |
Config file path |
If the config file already exists, the command prints a notice and does not overwrite it.
sendparcel providers
Lists all installed providers in a Rich table with their slug, display name, confirmation method, supported countries, and configuration status (OK if all required fields are present, --- otherwise).
| Option | Type | Default | Description |
|---|---|---|---|
--config |
Path |
~/.config/sendparcel/config.toml |
Config file path |
sendparcel check-config <slug>
Displays a detailed table for a specific provider's configuration. Each field shows whether it is required, its type, its current value (secrets are masked), and status (OK / MISSING / ---).
| Argument/Option | Type | Default | Description |
|---|---|---|---|
slug |
str |
(required) | Provider slug (e.g. inpost_locker) |
--config |
Path |
~/.config/sendparcel/config.toml |
Config file path |
Exits with code 1 if the provider slug is not found.
sendparcel create-label <slug>
Creates a test shipment through the full ShipmentFlow pipeline (create shipment + create label) and saves the label file to disk.
| Argument/Option | Type | Default | Description |
|---|---|---|---|
slug |
str |
(required) | Provider slug |
--config |
Path |
~/.config/sendparcel/config.toml |
Config file path |
--sender-file |
Path |
None |
Sender address JSON file |
--receiver-file |
Path |
None |
Receiver address JSON file |
--sender-first-name |
str |
None |
Sender first name (inline) |
--sender-last-name |
str |
None |
Sender last name (inline) |
--sender-phone |
str |
None |
Sender phone (inline) |
--sender-email |
str |
None |
Sender email (inline) |
--sender-street |
str |
None |
Sender street (inline) |
--sender-building-number |
str |
None |
Sender building number (inline) |
--sender-city |
str |
None |
Sender city (inline) |
--sender-postal-code |
str |
None |
Sender postal code (inline) |
--sender-country-code |
str |
None |
Sender country code (inline) |
--sender-company |
str |
None |
Sender company name (inline) |
--receiver-first-name |
str |
None |
Receiver first name (inline) |
--receiver-last-name |
str |
None |
Receiver last name (inline) |
--receiver-phone |
str |
None |
Receiver phone (inline) |
--receiver-email |
str |
None |
Receiver email (inline) |
--receiver-street |
str |
None |
Receiver street (inline) |
--receiver-building-number |
str |
None |
Receiver building number (inline) |
--receiver-city |
str |
None |
Receiver city (inline) |
--receiver-postal-code |
str |
None |
Receiver postal code (inline) |
--receiver-country-code |
str |
None |
Receiver country code (inline) |
--receiver-company |
str |
None |
Receiver company name (inline) |
--weight |
float |
1.0 |
Parcel weight in kg |
--output-dir |
Path |
. (current dir) |
Directory to save the label file |
--kwarg |
str |
None |
Provider kwargs as KEY=VALUE (repeatable) |
Addresses can be provided three ways:
- JSON file only —
--sender-file sender.json - Inline flags only —
--sender-first-name "Jan" --sender-last-name "Nadawca" ... - Combined — load a base from file, override specific fields with inline flags
At least one of sender or receiver address must be provided. Exits with code 1 if neither is given or if the provider slug is not found.
Address JSON format
{
"first_name": "Jan",
"last_name": "Nadawca",
"phone": "500100200",
"email": "sender@test.com",
"street": "Testowa",
"building_number": "1",
"city": "Warszawa",
"postal_code": "00-001",
"country_code": "PL"
}
Optional fields: company, flat_number.
Provider kwargs
Use --kwarg KEY=VALUE to pass provider-specific parameters. This flag is repeatable:
sendparcel create-label inpost_locker \
--sender-file sender.json \
--receiver-file receiver.json \
--kwarg target_point=KRA010 \
--kwarg sending_method=dispatch_order
These kwargs are forwarded directly to ShipmentFlow.create_shipment() and ShipmentFlow.create_label().
Label Handling
The create-label command saves labels to disk automatically:
- Base64 payloads from
label["content_base64"]are decoded and saved as binary.pdffiles. - URL results from
label["url"]are saved as text files containing the URL. - Binary labels are saved as
label-<external_id>.pdf; URL-only labels are saved aslabel-<external_id>.txt.
Programmatic Usage
While primarily a CLI tool, the package exports its models and config manager for scripting:
from sendparcel_cli import CLIShipment, CLIShipmentRepository, ConfigManager
# Load config
mgr = ConfigManager() # uses default path
config = mgr.get_provider_config("inpost_locker")
# In-memory shipment + repository for scripting
shipment = CLIShipment(provider="inpost_locker")
repo = CLIShipmentRepository()
Error Handling
The CLI handles errors with colored Rich output and appropriate exit codes:
| Situation | Behavior |
|---|---|
| Unknown provider slug | Prints Provider '<slug>' not found. in red, exits with code 1 |
| Missing sender/receiver addresses | Prints error message, exits with code 1 |
Invalid --kwarg format |
Raises BadParameter with format hint |
| Address file not found | Raises BadParameter with file path |
Config file already exists (init) |
Prints notice, does not overwrite |
| Label creation failure | Silently suppressed (shipment result is still displayed) |
| Any other provider error | Prints error in red, exits with code 1 |
Supported Versions
| Dependency | Version |
|---|---|
| Python | >= 3.12 |
| python-sendparcel | >= 0.1.1 |
| typer | >= 0.15.0 |
| rich | >= 13.0 |
| tomli-w | >= 1.0 |
Running Tests
The test suite uses pytest with pytest-asyncio (asyncio_mode = "auto")
and Typer's CliRunner for command testing.
# Install dev dependencies
uv sync --extra dev
# Run the full test suite
uv run pytest
# With coverage
uv run pytest --cov=sendparcel_cli --cov-report=term-missing
Test coverage includes:
test_config.py—ConfigManagerload/save/roundtrip, provider config get/set, flow config format, default path resolution.test_main.py— all four CLI commands tested viaCliRunner:init(create + no-overwrite),providers(listing),check-config(missing fields + unknown provider),create-label(JSON files, inline flags, kwarg passthrough, missing addresses).test_models.py—CLIOrder,CLIShipment,CLIShipmentRepositoryprotocol conformance, weight calculation, unique IDs, mutable fields, async CRUD operations.test_output.py— Rich table rendering for providers, shipment results, and config checks including secret masking.
Credits
- Author: Dominik Kozaczko (dominik@kozaczko.info)
- Built on top of python-sendparcel core library
- CLI powered by Typer and Rich
License
Project details
Release history Release notifications | RSS feed
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 python_sendparcel_cli-0.1.1.tar.gz.
File metadata
- Download URL: python_sendparcel_cli-0.1.1.tar.gz
- Upload date:
- Size: 14.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
674b2f1e22a25f2711582165c2624d7285a82c9473288d9525da7dde139b202e
|
|
| MD5 |
c46d0ee2452b0dffb19c95b1364785a7
|
|
| BLAKE2b-256 |
1add1099e5def93675cc87809f2449b134b27e27816d3ff6d0ccbfa31b4171a7
|
File details
Details for the file python_sendparcel_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: python_sendparcel_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
690ba39782a3e7e989b4acad8d7fa0c6179c4860d9fc90eae904b9407a666dab
|
|
| MD5 |
2a4ddf5f442fdcdde309f208f0d70b35
|
|
| BLAKE2b-256 |
f817efdd2cab19e23315d4a2e4527c088bee2efd92e92bd3069796bfea9e2de1
|