Skip to content

Latest commit

 

History

History
281 lines (207 loc) · 9.8 KB

File metadata and controls

281 lines (207 loc) · 9.8 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Auto-memory policy

Do NOT use MEMORY.md. Never write to MEMORY.md or any file under the memory directory. All behavioral rules, conventions, and workflow instructions belong in managed, version-controlled documentation (CLAUDE.md, AGENTS.md, skills, or docs/). If you want to persist something, tell the human what you would save and let them decide where it belongs.

Project Overview

pymqrest is a Python wrapper for the IBM MQ administrative REST API. The project provides a Python mapping layer for MQ REST API attribute translations and command metadata experiments. The current focus is on attribute mapping and metadata modeling.

Status: Beta

Canonical Standards: This repository follows standards at https://github.com/wphillipmoore/standards-and-conventions (local path: ../standards-and-conventions if available)

Development Commands

Standard Tooling

git config core.hooksPath ../standard-tooling/scripts/lib/git-hooks  # Enable git hooks

Standard-tooling CLI tools (st-commit, st-validate-local, etc.) are pre-installed in the dev container images. No local setup required.

Environment Setup

# Install dependencies and sync environment
uv sync --group dev

Three-Tier CI Model

Testing is split across three tiers with increasing scope and cost:

Tier 1 — Local pre-commit (seconds): Fast smoke tests in a single container. Run before every commit. No MQ, no matrix.

./scripts/dev/test.sh        # Unit tests in dev-python:3.14
./scripts/dev/lint.sh        # Ruff check + format in dev-python:3.14
./scripts/dev/typecheck.sh   # mypy + ty in dev-python:3.14
./scripts/dev/audit.sh       # pip-audit in dev-python:3.14

Tier 2 — Push CI (~3-5 min): Triggers automatically on push to feature/**, bugfix/**, hotfix/**, chore/**. Single Python version (3.14), includes integration tests, no security scanners or release gates. Workflow: .github/workflows/ci-push.yml (calls ci.yml).

Tier 3 — PR CI (~8-10 min): Triggers on pull_request. Full Python matrix (3.12, 3.13, 3.14), all integration tests, security scanners (CodeQL, Trivy, Semgrep), standards compliance, and release gates. Workflow: .github/workflows/ci.yml.

Validation

# Run full validation suite (matches CI hard gates)
uv run python3 scripts/dev/validate_local.py

# Docs-only validation (requires markdownlint on PATH)
uv run python3 scripts/dev/validate_docs.py

The full validation suite includes:

  • Virtual environment validation
  • Dependency specification validation
  • Version validation
  • Repository profile linting
  • Markdown standards checking
  • Commit message validation
  • Lock file verification
  • Security audit (pip-audit)
  • Ruff linting and formatting
  • mypy type checking
  • ty type checking
  • pytest with 100% coverage requirement

Testing

# Run tests with coverage
uv run pytest --cov=pymqrest --cov-report=term-missing --cov-branch --cov-fail-under=100

# Run specific test file
uv run pytest tests/pymqrest/test_session.py

# Run integration tests (requires local MQ container)
MQ_REST_ADMIN_RUN_INTEGRATION=1 uv run pytest -m integration

Linting and Formatting

# Run Ruff linter
uv run ruff check

# Run Ruff formatter (check only)
uv run ruff format --check .

# Run Ruff formatter (fix)
uv run ruff format .

# Run mypy type checker
uv run mypy src/

# Run ty type checker
uv run ty check src

Publishing

The publish.yml workflow triggers on push to main and publishes to PyPI via OIDC trusted publishing. It builds with uv build, publishes via pypa/gh-action-pypi-publish, creates a git tag, and a GitHub Release. The release flow is: developrelease/*main (merge commit). See docs/sphinx/development/release-workflow.md for the full process.

Local MQ Container

The MQ development environment is owned by the mq-rest-admin-dev-environment repository. Clone it as a sibling directory before running lifecycle scripts:

# Prerequisite (one-time)
git clone https://github.com/wphillipmoore/mq-rest-admin-dev-environment.git ../mq-rest-admin-dev-environment

# Start the containerized MQ queue managers
./scripts/dev/mq_start.sh

# Seed deterministic test objects (DEV.* prefix)
./scripts/dev/mq_seed.sh

# Verify REST-based MQSC responses
./scripts/dev/mq_verify.sh

# Stop the queue managers
./scripts/dev/mq_stop.sh

# Reset to clean state (removes data volumes)
./scripts/dev/mq_reset.sh

The lifecycle scripts are thin wrappers that delegate to ../mq-rest-admin-dev-environment. Override the path with MQ_DEV_ENV_PATH.

Container details:

  • Queue managers: QM1 and QM2
  • QM1 ports: 1414 (MQ listener), 9443 (mqweb console + REST API)
  • QM2 ports: 1415 (MQ listener), 9444 (mqweb console + REST API)
  • Admin credentials: mqadmin / mqadmin
  • Read-only credentials: mqreader / mqreader
  • QM1 REST base URL: https://localhost:9443/ibmmq/rest/v2
  • QM2 REST base URL: https://localhost:9444/ibmmq/rest/v2
  • Object prefix: DEV.*

Port assignments are explicit in each scripts/dev/mq_*.sh script via QM1_REST_PORT, QM2_REST_PORT, QM1_MQ_PORT, and QM2_MQ_PORT exports. Python uses the base ports (9443/9444, 1414/1415). See the port allocation table in mq-rest-admin-common for the full cross-language map.

Architecture

Core Components

Session Management (src/pymqrest/session.py):

  • MQRESTSession owns authentication, base URL construction, and request/response handling
  • _run_command_json is the single internal executor for MQSC commands via runCommandJSON
  • Supports basic auth and CSRF token handling
  • Transport abstraction via MQRESTTransport protocol

Command Methods (src/pymqrest/commands.py):

  • MQRESTCommandMixin provides ~2000 lines of generated MQSC command wrappers
  • Method naming: <verb>_<qualifier> (lowercase, spaces to underscores)
  • All methods accept optional name, request_parameters, and response_parameters
  • DISPLAY commands return lists of dict-like objects
  • Non-DISPLAY commands return None

Attribute Mapping (src/pymqrest/mapping.py):

  • Runtime attribute mapping: MQSC ↔ PCF ↔ snake_case translations
  • map_request_attributes() converts Python-friendly names to MQSC format
  • map_response_attributes() converts MQSC responses to Python-friendly format
  • MappingIssue captures translation problems for diagnostics
  • MappingError raised on mapping failures with detailed issue list

Mapping Data (src/pymqrest/mapping_data.py + src/pymqrest/mapping-data.json):

  • mapping_data.py is a thin loader that reads mapping-data.json at import time
  • The JSON file contains all qualifier and attribute mappings
  • _mapping_merge.py provides MappingOverrideMode for runtime mapping overrides

Authentication (src/pymqrest/auth.py):

  • CertificateAuth - mutual TLS client certificates
  • LTPAAuth - LTPA token login (automatic at session creation)
  • BasicAuth - HTTP Basic authentication
  • Credentials - union type for all credential types

Ensure Methods (src/pymqrest/ensure.py):

  • Idempotent ensure_* methods: DEFINE if missing, ALTER if different, no-op if matching
  • EnsureAction enum: CREATED, UPDATED, UNCHANGED
  • EnsureResult dataclass with action and changed attributes

Sync Wrappers (src/pymqrest/sync.py):

  • Synchronous start/stop/restart with polling until target state is reached
  • SyncConfig for timeout and poll interval settings
  • SyncResult with operation performed and timing

Exceptions (src/pymqrest/exceptions.py):

  • MQRESTError - base exception
  • MQRESTTransportError - network/connection failures
  • MQRESTAuthError - authentication failures
  • MQRESTTimeoutError - sync polling timeouts
  • MQRESTResponseError - invalid response format
  • MQRESTCommandError - MQSC command execution failures

Key Design Patterns

  1. Single Endpoint: All MQSC operations go through the runCommandJSON REST endpoint
  2. Attribute Mapping Pipeline: MQSC → PCF → snake_case (bidirectional)
  3. Mapping Opt-Out: Can be disabled at session creation or per method call
  4. Error Payloads: Captured for diagnostics
  5. Response Parameters Default: ["all"] when omitted

Generated Code

  • src/pymqrest/commands.py is generated (methods omit per-method docstrings per ruff config)
  • Generation scripts in scripts/dev/ regenerate code from MAPPING_DATA

Important Implementation Notes

MQSC Command Execution

The runCommandJSON payload structure:

{
  "type": "runCommandJSON",
  "command": "DISPLAY",
  "qualifier": "QLOCAL",
  "name": "QUEUE.NAME",
  "parameters": {},
  "responseParameters": ["all"]
}

For queue manager queries, name is omitted.

Mapping Pipeline

When mapping is enabled (default):

  1. Request: Python snake_case → MQSC names
  2. MQ REST API execution
  3. Response: MQSC names → Python snake_case

Mapping can be disabled per-session or per-call with map_attributes=False.

Error Handling

  • DISPLAY methods return empty lists for missing objects (no exception)
  • Queue manager DISPLAY methods return None for missing objects
  • DEFINE and DELETE methods raise on errors
  • Error payloads stored on session for diagnostics

Key References

External Documentation:

  • IBM MQ 9.4 administrative REST API
  • MQSC command reference
  • PCF command formats

Temporary Workarounds

Codex Branch Deletion: The Codex execution harness may reject git branch -d even with sandbox_mode = "danger-full-access". Workaround: use git update-ref -d refs/heads/<branch> when cleanup is required.