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.jsonand 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 witha*a-> ends withaa-> 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>)
- base excludes:
- 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:
- config_usage.py - Server configuration examples
- filter.txt - Filter pattern 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
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 tm1gitpy-1.1.0.tar.gz.
File metadata
- Download URL: tm1gitpy-1.1.0.tar.gz
- Upload date:
- Size: 157.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cd2c78b1f68c9bc1cbdfb9408351d58e1605dce2e7cce7556b0f501abc016ce
|
|
| MD5 |
685dbbb2ac38aebcb1ec36edfee71815
|
|
| BLAKE2b-256 |
b112e8c6947a12620a8c399b6c9eb4ef9f466cfaa1cd583847a8286b901fbcbe
|
File details
Details for the file tm1gitpy-1.1.0-py3-none-any.whl.
File metadata
- Download URL: tm1gitpy-1.1.0-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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cb7a3ac2e02163939fc5e7842b2ad931576d99726449bb51d56db045f36f9cb
|
|
| MD5 |
dea67f2ad9cfe4d64b4063915c880c92
|
|
| BLAKE2b-256 |
0b156700cbc701839734ca4af8d5495e986d58dcd6993d116f2718db39d23cfb
|