Skip to main content

A TM1py-inspired Python wrapper for the IBM Planning Analytics Workspace (PAW) REST API.

Project description

PAWpy — Planning Analytics Workspace REST API Wrapper

PyPI version Python versions License: MIT

A TM1py-inspired Python wrapper for the PAW REST API.

Install

uv sync --extra dev         # installs PAWpy + pytest
uv run python -m pytest     # 21 offline tests (no live server needed)

Requires Python ≥3.11 and requests. The URL-builder calls (paw.ui.*, *.get_embed_url) make no network request and work without a live PAW server.

Releasing

Publishing is automated by .github/workflows/publish.yml via PyPI Trusted Publishing (OIDC — no API token stored). To cut a release:

  1. Bump version in pyproject.toml and add a CHANGELOG.md entry.
  2. One-time on PyPI: add a Trusted Publisher for project PAWpybluestarleo/PAWpy, workflow publish.yml, environment pypi.
  3. Tag and push:
    git tag v0.1.0 && git push origin v0.1.0
    

The workflow runs the tests (3.11–3.13), builds, checks the tag matches the package version, and publishes the sdist + wheel to PyPI.

Architecture

PAWService                  ← top-level entry point (mirrors TM1py's TM1Service)
├── RestService             ← session + auth + GET/POST/PATCH/PUT/DELETE core
├── ContentService          ← /pacontent/v1/Assets  (legacy OData folders / books / assets)
├── ContentV1Service        ← /api/v1/content  (OAuth-era assets, permissions,
│                             bulk ops, asset types — PAW 2.1.21+/3.1.8+)
├── UserGroupService        ← /api/v1/content/users|groups  (PAW 2.1.21+/3.1.8+)
├── BookService             ← books (type=book/dashboard) over ContentService
├── ViewService             ← views over ContentService
├── AdminService            ← /api/v1/admin  (servers, users, groups)
├── UIService               ← URL builder for /ui?type=… embed endpoints
└── TM1ProxyService         ← /api/v0/tm1/<db>/api/v1/…  (TM1 REST via PAW auth;
                              pass tm1_proxy_base="/api/v1/tm1" on PAW 2.1.21+/3.1.8+)

All base paths (content_base, admin_base) are constructor-overridable, since they vary across PAW builds (/pacontent/v1 vs /api/v1/content).

Auth Modes

Mode How it works
oauth Client-credentials grant against an IdP token_urlAuthorization: Bearer (see caveat below)
cam CAM namespace login via POST /loginx-csrf-token — the proven headless mode for on-prem PAW
native TM1 native username/password login via POST /loginx-csrf-token
passport Cognos CAM passport (camid) via POST /login
session Inject an existing csrf_token / session_cookie (dev/test)

On-prem OAuth caveat (per IBM Docs, "Configuring authorized applications (OAuth)"): PAW's built-in OAuth (Administration → Integrations tile, PAW 2.1.21+/3.1.8+) supports only the interactive authorization-code flow (scope v0userContext) — "client credentials (not interactive) flows are not supported" against PAW's own /oauth2/token. Use oauth mode only where an external IdP issues bearer tokens your PAW deployment accepts. For headless/scripted access to on-prem PAW, use cam mode with directory credentials (PAW shares the CAM directory with TM1, so TM1 service credentials typically work). Authorization-code + refresh-token support is on the roadmap.

Usage

OAuth (IdP-issued tokens — see caveat above)

from PAWpy import PAWService

with PAWService(
    host="paw.mycompany.com",
    auth_mode="oauth",
    client_id="my-client-id",
    client_secret="my-client-secret",
    token_url="https://idp.mycompany.com/oauth2/token",  # required for oauth
    scope="paw",                    # optional
    database="Planning Sample",          # optional default TM1 database
) as paw:

    # List books in a folder (returns Asset objects)
    books = paw.books.get_all("/shared/Finance")

    # Get embed URL for an iframe (no HTTP call)
    url = paw.books.get_embed_url("/shared/Finance/Monthly Report")

    # List registered TM1 servers
    servers = paw.admin.get_tm1_servers()

    # OAuth-era content API (PAW 2.1.21+/3.1.8+): permissions, bulk ops, users
    assets = paw.content_v1.list_children("shared")
    perms  = paw.content_v1.get_effective_permissions(assets[0].id)
    users  = paw.user_groups.get_users()

    # TM1 proxy call (MDX via PAW auth) — returns the raw cellset JSON
    tm1 = paw.tm1("Planning Sample")
    data = tm1.execute_mdx("SELECT {[Account].[Revenue]} ON 0 FROM [Revenue Cube]")

    # Embed URL generation (no HTTP call)
    embed = paw.ui.cube_viewer_url("Planning Sample", "plan_BudgetPlan", view="Budget Input")

CAM (headless on-prem — recommended for scripts)

with PAWService(
    host="paw.mycompany.com",
    auth_mode="cam",
    namespace="LDAP",
    username="my-username",
    password="secret",
) as paw:
    ...

Multi-tenant (PAW Cloud)

with PAWService(
    host="planning-analytics.cloud.ibm.com",
    tenant_id="my-tenant-id",
    auth_mode="oauth",
    client_id="...",
    client_secret="...",
) as paw:
    ...

Mapping to TM1py

TM1py PAWpy
TM1Service PAWService
CubeService TM1ProxyService (via PAW)
DimensionService TM1ProxyService (via PAW)
ProcessService TM1ProxyService (via PAW)
(no equivalent) BookService
(no equivalent) ContentService
(no equivalent) AdminService
(no equivalent) UIService

Versioning against PAW builds

The PAW REST API is still incomplete and grows with each IBM release, so PAWpy is versioned against two axes: its own semver (PAWpy.__version__) and the minimum PAW build each API group requires. Each service declares its API_GROUP; the per-group minimums live in PAWpy/version_requirements.py (MIN_PAW_VERSION).

paw = PAWService(host="paw.acme.com", auth_mode="oauth", ..., paw_version="2.1.21")

paw.requires("content")          # -> "2.1.21"  (min PAW build for Content Services)
paw.supports("content")          # -> True / False against the known paw_version
paw.assert_supported("content")  # raises PAWVersionError if the build is too old
paw.detect_paw_version()         # best-effort probe (overridable path/field)

When paw_version is unknown, gating is a no-op — PAWpy never blocks a call solely because it couldn't determine the version; the server still rejects genuinely-unsupported requests. The version pins are reconciled on each PAW release as part of a maintainer-local workflow.

Coverage & release tracking

PAWpy's endpoint coverage is tracked in a maintainer-local coverage matrix (not part of this repo). Because the PAW REST API is still growing, it is reconciled on each PAW release: IBM's endpoint inventory (the IBM-linked Postman collection or the published API references) is re-pulled and diffed against the matrix to flag endpoints PAW now exposes that PAWpy doesn't yet wrap, so the wrapper tracks IBM's cadence instead of drifting. New coverage lands here as Added entries in CHANGELOG.md and Roadmap items below.

Roadmap (aligned with IBM's "future releases" promise)

  • Content API v1 (/api/v1/content, PAW 2.1.21+/3.1.8+) — ContentV1Service: assets incl. content retrieval, permissions (get/set/effective), bulk copy/move/delete/permissions, asset types
  • UserGroupService — PAW users/groups reads (/api/v1/content/users|groups); write endpoints not yet documented by IBM
  • ViewService — PAW view CRUD
  • EmbedTokenService — generate scoped embed tokens
  • MCPService — PAW MCP endpoint integration
  • OAuth authorization-code + refresh-token flow — the only OAuth on-prem PAW supports (client-credentials is rejected per IBM Docs)
  • Async support (aiohttp)
  • Pydantic models for Books, Assets, Servers

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

pawpy-0.4.1.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

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

pawpy-0.4.1-py3-none-any.whl (32.1 kB view details)

Uploaded Python 3

File details

Details for the file pawpy-0.4.1.tar.gz.

File metadata

  • Download URL: pawpy-0.4.1.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pawpy-0.4.1.tar.gz
Algorithm Hash digest
SHA256 d2b36708cdaa616d6fa11193e6133f085352de603ac32ff125a302a36669ac0f
MD5 843a80d45b6a2bf273799342a8fc4e9a
BLAKE2b-256 632e265da74aa2c28c72e20f29eace194e2b42ad372fcfe7bc4fc51b2acf795b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pawpy-0.4.1.tar.gz:

Publisher: publish.yml on bluestarleo/PAWpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pawpy-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: pawpy-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 32.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pawpy-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 19931598899407144d602665e59d5391b2cdd93864873fa3827c64be268a05ae
MD5 fcbe13590dcd0322a3151f778fcd9056
BLAKE2b-256 e64358a32913f720cd47c5edc632c7ec98d732f587eea03e3d1f2755193a2a24

See more details on using hashes here.

Provenance

The following attestation bundles were made for pawpy-0.4.1-py3-none-any.whl:

Publisher: publish.yml on bluestarleo/PAWpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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