Skip to main content

Utilities for exporting and comparing TM1 models for Git workflows.

Project description

tm1_git_py

tm1_git_py is a Python-based drop-in replacement for TM1 Git. It keeps TM1 Git’s on-disk file layout so you can move between tools with minimal friction.

  • It understands tm1project.json and the same filtering rules used by TM1 Git workflows.
  • It is not embedded in TM1, which keeps deployment flexible—ideal for CI/CD, agents, and pipelines that run outside the TM1 server. It talks to TM1 over the REST API via TM1py.
  • You can run it as a stand-alone command-line tool or import it as a library and embed it in a larger ecosystem (automation, CI/CD, custom apps).

Features

tm1_git_py allows you to:

  • Export TM1 models (cubes, dimensions, processes, chores) to a structured folder format compatible with TM1 Git
  • Filter exports to include only specific objects
  • Compare models (either file-based schema or TM1 servers) and collect differences to changesets.
  • Apply changsets to target server

Installation

From Source

To use the package (runtime dependencies only):

git clone <repository-url>
cd tm1_git_py
pip install -e .

Or install from a requirements file: pip install -r requirements.txt then pip install -e .

To run tests or develop (runtime + test dependencies):

pip install -r requirements-dev.txt
# or
pip install -e ".[dev]"

Requirements

  • Python 3.10 or higher
  • TM1py >= 2.1, < 3.0
  • requests >= 2.25
  • PyYAML >= 6.0

Configuration

Create a configuration file at .tm1gitpy/tm1servers.yaml (local directory) or ~/.tm1gitpy/tm1servers.yaml (user home):

servers:
  dev:
    base_url: http://localhost:12354/api/v1/
    user: admin
    password: your_password  # Optional - can use environment variables
  
  prod:
    base_url: https://prod-server.company.com:12354/api/v1/
    user: admin
    password: ${TM1_PROD_PASSWORD}  # Environment variable placeholder

Usage

Export TM1 Model

Export a full TM1 model from a server:

python tm1_git_py/main.py export --server dev --model-output-folder model_dir --overwrite

Filter Model

Apply filters to include only specific objects:

python tm1_git_py/main.py model-filter --filter-rules file://examples/filter.txt --model-folder model_dir --model-output-folder model_dir_filtered --overwrite

Toggle apply flags inside an existing changeset with the same filter rule language:

python tm1_git_py/main.py changset-filter --changeset-path changeset.yml --filter-rules file://examples/filter.txt

Filter file format (one pattern per line, # for comments):

# Exclude technical dimensions
Dimensions('}*')

# Force-include all BW dimensions
!Dimensions('BW*')

# Exclude BW Comp dimensions
Dimensions('BW Comp*')

# Exclude technical hierarchies for all dimensions
Dimensions('*')/Hierarchies('}*')

# Chore task rules target the underlying process_name
Chores('Daily*')/Tasks('LoadData')

Filter Rule Logic

  • Each rule line is a TM1 URL-style selector, optionally prefixed with !.
  • No prefix means exclude.
  • ! prefix means force include.
  • Wildcards in quoted identifiers are supported:
    • a* -> starts with a
    • *a -> ends with a
    • a -> exact match
  • Rules are evaluated per entity level (dimensions, hierarchies, elements, subsets, cubes, views, processes, chores, tasks).
  • Hierarchy traversal is parent-first, with force-include branch retention:
    • normally, excluded parent excludes descendants
    • if a descendant is force-included (!), its required parent chain is retained (e.g. force-include element keeps matching hierarchy and dimension references)
  • At each level, filter expression is composed as:
    • base excludes: not (<exclude_1>) and not (<exclude_2>) and ...
    • plus force includes: or (<include_group>)
    • effective shape: (not (<exclude_1>) and not (<exclude_2>) and ...) or (<include_group>)
  • TM1 export filters inherit force-includes from descendants:
    • a force-included hierarchy contributes include criteria to the dimension-level TM1 filter
    • a force-included element/subset/edge contributes include criteria to the hierarchy-level TM1 filter

Supported Rule Patterns

Level Pattern
Dimension Dimensions('<pattern>')
Hierarchy Dimensions('<dim_pattern>')/Hierarchies('<hier_pattern>')
Element Dimensions('<dim_pattern>')/Hierarchies('<hier_pattern>')/Elements('<elem_pattern>')
Subset Dimensions('<dim_pattern>')/Hierarchies('<hier_pattern>')/Subsets('<subset_pattern>')
Edge Dimensions('<dim_pattern>')/Hierarchies('<hier_pattern>')/Edges(...)
Cube Cubes('<pattern>')
View Cubes('<cube_pattern>')/Views('<view_pattern>')
Rule Cubes('<cube_pattern>')/Rules(...)
Process Processes('<pattern>')
Chore Chores('<pattern>')
Task Chores('<chore_pattern>')/Tasks('<process_name_pattern>')

Use ! prefix on any supported pattern to force-include matching objects.

Filter Rule Input Formats (CLI)

For CLI flags that accept filter rules (--filter or --filter-rules):

  • File path: examples/filter.txt
  • File URI: file://examples/filter.txt
  • Inline comma-separated rules: Dimensions('}*'),!Dimensions('BW*')

Command-Line Arguments

python tm1_git_py/main.py <command> [options]

Commands:
  export    Export TM1 model from server
  model-filter    Filter an existing model export
  changset-filter Toggle changeset apply flags by filter rules
  compare   Compare two model versions and write a changeset file
  apply     Apply a changeset file to a TM1 server

Options:
  -s, --server SERVER           TM1 server name from tm1servers.yaml
  -m, --model-folder FOLDER     Input model folder (default: export)
  -mo, --model-output-folder    Output model folder (default: export)
  -o, --overwrite              Overwrite existing folder
  -f, --filter FILE            Filter rules for export (file path, file:// URI, or comma-separated rules)
  -f, --filter-rules RULES     Filter rules for compare/model-filter/changset-filter
  --changeset-path PATH         Changeset path for changset-filter
  --max-workers N              Worker budget for export/compare (default: cpu_count/2 + 1)
  --log-level LEVEL            Log level: DEBUG, INFO, WARNING, ERROR

Logging defaults to INFO. You can also set TM1GITPY_LOG_LEVEL in the environment; --log-level takes precedence.

For compare, --max-workers is split between source and target model deserialization:

  • source workers = max(1, max_workers // 2)
  • target workers = max(1, max_workers - source_workers)
  • odd values give one extra worker to target

Examples

See the examples directory for usage examples:

For model comparison and changeset workflows, use the Python API (tm1_git_py.comparator, tm1_git_py.changeset, tm1_git_py.apply).

For paginated element/subset fetching (e.g., large hierarchies), use tm1_git_py.get_elements, tm1_git_py.get_subsets, and related functions.

Building Binary

Build a standalone executable using Nuitka:

python -m nuitka tm1_git_py/main.py --follow-imports --no-deployment-flag=self-execution --mode=onefile --output-filename=tm1gitpy

Development

Running Tests

pytest tests/

Integration tests (TM1 container/local TM1 required):

PYTHONPATH=. pytest test_integration/

Project Structure

tm1_git_py/
├── tm1_git_py/          # Main package
│   ├── main.py          # CLI entry point
│   ├── config.py        # Server configuration
│   ├── exporter.py      # TM1 model export
│   ├── hierarchy_export.py  # Hierarchy export logic
│   ├── serializer.py    # Model serialization
│   ├── deserializer.py  # Model deserialization
│   ├── filter.py        # Object filtering
│   ├── comparator.py    # Compare TM1 models
│   ├── changeset.py     # Build changeset
│   ├── apply.py         # Apply changeset
│   ├── logging_config.py   # Logging setup
│   ├── changeset_status.py # Changeset status tracking
│   ├── validation.py    # Validation utilities
│   ├── tm1project_to_filter.py  # TM1 project to filter conversion
│   ├── tm1py_ext/       # TM1py extensions and paginated services
│   │   ├── paginated_element_service.py
│   │   ├── paginated_subset_service.py
│   │   └── paginated_edge_service.py
│   └── model/           # Model data structures
│       ├── element_attribute.py
│       ├── task_summary.py
│       └── ...
├── examples/            # Usage examples
├── docs/               # Documentation
├── tests/              # Test suite
└── test_integration/   # Integration tests

License

See LICENSE file for details.

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

tm1gitpy-1.1.1.tar.gz (157.4 kB view details)

Uploaded Source

Built Distribution

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

tm1gitpy-1.1.1-py3-none-any.whl (182.7 kB view details)

Uploaded Python 3

File details

Details for the file tm1gitpy-1.1.1.tar.gz.

File metadata

  • Download URL: tm1gitpy-1.1.1.tar.gz
  • Upload date:
  • Size: 157.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for tm1gitpy-1.1.1.tar.gz
Algorithm Hash digest
SHA256 2d94292bd1155d238189427c9901a85070cf6cd4dfa818db998b15566cf485c4
MD5 9ed898d00c8329535734f5e2ec37cfa6
BLAKE2b-256 9e8065701178903bbaae43e037cf7842b14ec27282fa65ad59deaa7a9ffb4756

See more details on using hashes here.

File details

Details for the file tm1gitpy-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: tm1gitpy-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 182.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for tm1gitpy-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a41f9cf7932b9487d0890216c455e84f58c58c2281da33bf9233c503aa169f73
MD5 43e2e166d63f6dca2a1472f2ddb0a8b9
BLAKE2b-256 d5abd159c822f17a42664e0169ba2449d1de0efd30fbfec6e54907bb83c9dbb8

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