Skip to main content

Unified multi-carrier tracking (FedEx implemented; UPS/USPS pending)

Project description

daylily-carrier-tracking

Unified multi-carrier package tracking library + CLI.

Implementation status

  • FedEx: implemented (OAuth2 + Track API v1, with optional Ship fallback)
  • UPS: scaffolded (config + CLI plumbing; live tracking not implemented yet)
  • USPS: scaffolded (config + CLI plumbing; live tracking not implemented yet)

Install

Recommended (development, isolated virtualenv)

This repo includes a helper script that always installs into a local ./.venv so you don't accidentally pip install -e . into your system/base Python.

./dev-setup.sh

If you want the venv activated in your current shell (so tday ... works without ./), source it:

. ./dev-setup.sh

After setup you can run either:

./tday --help   # wrapper; prefers ./.venv/bin/python automatically
tday --help     # console script (when your venv is active)

Manual install (advanced)

Only do this if you know what you're doing; the helper above is safer.

python3 -m venv .venv
. .venv/bin/activate
pip install -e .

direnv (optional)

.envrc is gitignored by design. Use the provided example:

cp .envrc.example .envrc
direnv allow

Repo checkout usage without install

You can run the repo wrapper directly; if ./.venv exists it will be used automatically.

./tday --help

Deprecated wrapper

./tracking_day --help

Configuration

Config locations

New default location (preferred):

~/.config/daylily-carrier-tracking/<carrier>_<env>.yaml

Example:

~/.config/daylily-carrier-tracking/fedex_prod.yaml

Legacy fallback (for backward compatibility in some code paths):

~/.config/<carrier>/<carrier>_<env>.yaml

Environments

<env> is a free-form string used in the filename suffix.

  • Default: prod
  • Common alternatives: test, sandbox, dev

YAML examples

FedEx (required keys: oauth_url (or api_url), client_id, client_secret):

---
oauth_url: https://apis.fedex.com/oauth/token
client_id: "YOUR_FEDEX_CLIENT_ID"
client_secret: "YOUR_FEDEX_CLIENT_SECRET"

# Optional overrides:
track_url: https://apis.fedex.com/track/v1/trackingnumbers
ship_track_url: ""  # set to https://apis.fedex.com/ship/v1/trackingnumbers to enable ship fallback

UPS (scaffolded; doctor currently validates presence of client_id + client_secret):

---
client_id: "YOUR_UPS_CLIENT_ID"
client_secret: "YOUR_UPS_CLIENT_SECRET"

USPS (scaffolded; doctor currently validates presence of client_id + client_secret):

---
client_id: "YOUR_USPS_CLIENT_ID"
client_secret: "YOUR_USPS_CLIENT_SECRET"

Interactive wizard

Create/update config files interactively:

tday configure fedex --env prod
tday configure ups --env prod
tday configure usps --env prod

Notes:

  • configure fedex prompts for credentials and can validate them via an OAuth token request.
  • configure ups/usps currently writes a placeholder YAML and exits non-zero (see Exit Codes).

CLI

All commands:

tday --help
tday <command> --help

Global flags

  • --pretty: pretty-print JSON output (applies to JSON-producing commands like track)
  • --no-color: disable ANSI colored status output on stderr
    • Also respected via NO_COLOR=1

Shell tab completion (bash/zsh)

This repo includes completion scripts under ./completions/ and the CLI can also print them on-demand:

  • tday completion bash

  • tday completion zsh

  • Bash: completions/tday.bash

  • Zsh: completions/_tday

Bash

One-shot (current shell):

source <(tday completion bash)

Repo checkout (source file directly):

source /path/to/daylily-carrier-tracking/completions/tday.bash

To persist, add a source ... line to your ~/.bashrc (or equivalent), e.g.:

mkdir -p ~/.bash_completion.d
tday completion bash > ~/.bash_completion.d/tday
echo 'source ~/.bash_completion.d/tday' >> ~/.bashrc

Zsh

One-shot (current shell):

source <(tday completion zsh)

Install (write into a completions dir):

mkdir -p ~/.zsh/completions
tday completion zsh > ~/.zsh/completions/_tday

Then ensure your ~/.zshrc contains something like:

fpath=(~/.zsh/completions $fpath)
autoload -Uz compinit
compinit

Note: the completion targets the installed command name tday. If you mainly run the repo wrapper ./tday, use:

# activate the venv so the installed console script is on PATH
. ./.venv/bin/activate
tday --help

The completion scripts are intentionally registered only for the tday command name (not ./tday, and not the deprecated tracking_day).

tday test

Run unit tests.

tday test
tday test --test-fedex
tday test --test-ups
tday test --test-usps

Notes:

  • Carrier-specific test selection looks for tests/test_<carrier>_*.py.

tday configure

Interactive credential setup wizard.

tday configure <fedex|ups|usps> [--env prod] [--path /custom/path.yaml] [--skip-validate]

tday track

Perform a live tracking call and print a JSON result to stdout.

tday track <TRACKING_NUMBER> \
  --carrier auto|fedex|ups|usps \
  [--api-preference auto|track|ship] \
  [--no-raw] \
  [--pretty]

Key flags:

  • --carrier
    • auto uses detect_carrier() to guess a carrier (best-effort).
  • --no-raw omits the raw carrier payload from the returned JSON.
  • --api-preference (FedEx only)
    • track: Track API only
    • ship: Ship endpoint only (requires ship_track_url to be set)
    • auto: try Track first; if the response looks like “not found” and ship_track_url is configured, try Ship

Examples:

tday track 395579987149 --carrier fedex --api-preference auto --pretty --no-raw
tday track 1Z999AA10123456784 --carrier auto --pretty

tday doctor

Diagnose config + (optionally) test live FedEx OAuth/track.

tday doctor \
  [--all] \
  --carrier auto|fedex|ups|usps \
  [--env prod] \
  [--config-path /path/to/config.yaml] \
  [--no-network] \
  [--tracking-number <TRACKING_NUMBER>] \
  [--json]

Also supported:

  • --all: run doctor for fedex + ups + usps and emit a single aggregated JSON report (implies --json).
    • Note: --all currently cannot be combined with --config-path (no per-carrier overrides yet).

Examples and sample payloads: see docs/doctor-examples.md.

JSON output (--json)

--json prints structured JSON to stdout (CI/support-ticket friendly) and suppresses human/colored output.

High-level shape:

  • doctor_version
  • carrier: { requested, detected, effective }
  • env
  • python: { executable, version }
  • package: { file } (or { error })
  • config: { source, path, exists, keys, required, presence, valid, ... }
  • network: { requested, implemented, note, oauth, track }
  • tracking: { number, normalized, normalized_error }

Examples:

tday doctor --carrier fedex --env prod --tracking-number 395579987149 --json | jq
tday doctor --carrier ups --env prod --json | jq
tday doctor --carrier usps --env prod --json | jq

# Aggregate all carriers into one JSON report
tday doctor --all --env prod --json | jq

Carrier auto-detection

If you want doctor to infer carrier from the tracking number:

tday doctor --carrier auto --tracking-number <TRACKING_NUMBER> --json | jq

Deprecated aliases

These are kept for backward compatibility and map to track internally:

  • tday fedex <TN> [...]tday track <TN> --carrier fedex [...]
  • tday ups <TN> [...]tday track <TN> --carrier ups [...]
  • tday usps <TN> [...]tday track <TN> --carrier usps [...]

Exit codes (CI-friendly)

These are the current conventions used by the CLI:

tday doctor

  • 0: config valid (and any requested FedEx network checks succeeded)
  • 2: config missing/invalid (all carriers) OR other validation error
  • 3: FedEx OAuth token request failed
  • 4: FedEx live track call failed

In doctor --all mode, the overall exit code is the “most severe” code across carriers (priority: 4 > 3 > 2 > 0).

tday track

  • 0: success
  • 1: runtime error (exception)
  • 2: carrier not implemented / config issues resulting in NotImplementedError

tday configure

  • 0: wrote config (and validation succeeded, if applicable)
  • 2: UPS/USPS wizard is scaffolded (placeholder written)
  • 3: FedEx credential validation failed

tday test

  • 0: all selected tests passed
  • 2: tests/ missing, or a selected carrier test pattern matched no files
  • otherwise: underlying python -m unittest return code

CI (GitHub Actions) snippet

Minimal CI steps that (a) capture doctor --json output to files via tee, and (b) fail the job on non-zero exit codes.

Note: GitHub Actions run: steps use bash -e -o pipefail by default on Linux/macOS runners, so a failing tday doctor ... will still fail even when piped to tee.

- name: Doctor (UPS)
  run: tday doctor --carrier ups --env prod --json | tee ups_doctor.json

- name: Doctor (USPS)
  run: tday doctor --carrier usps --env prod --json | tee usps_doctor.json

- name: Doctor (ALL carriers, single JSON)
  run: tday doctor --all --env prod --json | tee doctor_all.json

Credential setup (how to obtain credentials)

This project expects you to create carrier developer credentials and store them locally in ~/.config/daylily-carrier-tracking/.

FedEx

Portals/docs (observed 2026-01-22):

Typical steps:

  1. Create/login to a FedEx Developer account.
  2. Create a project/app and enable APIs:
    • Track API (v1)
    • (Optional) Ship API if you want the ship fallback route
  3. Generate OAuth2 client credentials (client id / client secret).
  4. Create ~/.config/daylily-carrier-tracking/fedex_prod.yaml with oauth_url, client_id, client_secret.
  5. Validate:
tday doctor --carrier fedex --env prod --json | jq

Notes:

  • Production credentials may require additional FedEx account verification/approval.
  • Sandbox vs production endpoints/credentials are distinct; name your --env accordingly.

UPS

Portals/docs (observed 2026-01-22):

Typical steps:

  1. Create/login to a UPS Developer account.
  2. Create an app and subscribe to the APIs you need (e.g., Tracking).
  3. Generate OAuth client credentials.
  4. Create ~/.config/daylily-carrier-tracking/ups_prod.yaml with client_id and client_secret.
  5. Validate config presence (network checks not implemented yet):
tday doctor --carrier ups --env prod --json | jq

USPS

Portals/docs (observed 2026-01-22):

Typical steps:

  1. Create/login to the USPS Developer Portal.
  2. Request access to the relevant APIs for tracking.
  3. Create ~/.config/daylily-carrier-tracking/usps_prod.yaml with client_id and client_secret.
  4. Validate config presence (network checks not implemented yet):
tday doctor --carrier usps --env prod --json | jq

Note (time-sensitive): The USPS Web Tools page currently warns that legacy Web Tools APIs are being sunset (see USPS site for the current status).

Tests

python -m unittest discover -s tests

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

daylily_carrier_tracking-0.1.0.tar.gz (27.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

daylily_carrier_tracking-0.1.0-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file daylily_carrier_tracking-0.1.0.tar.gz.

File metadata

  • Download URL: daylily_carrier_tracking-0.1.0.tar.gz
  • Upload date:
  • Size: 27.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for daylily_carrier_tracking-0.1.0.tar.gz
Algorithm Hash digest
SHA256 45c1854857f7a6493350ef56e63b2eb1e44a1bf6d0ae46ede8cf56de14bb34f2
MD5 1e2d40c254bddbf0272507ee70773ab4
BLAKE2b-256 8991ce235c8159d9849e9b60b16998f3651cb6acd24140fa694b39bae4560fa0

See more details on using hashes here.

File details

Details for the file daylily_carrier_tracking-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for daylily_carrier_tracking-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90ba25948a4b46150e073ca8e27bed46a9b2d0fe661e1a46aa970f9c0f12f25f
MD5 48871696c4855f753ab02305608442e9
BLAKE2b-256 a99ca014127d6ce75f64ce75a32285616c4cdf8de5387e2932f2f48c89279a12

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page