1317 applicationservice fails to access applications inside private folders
Summary
Problem
The ApplicationService failed with 404 errors when accessing applications inside private folders because the TM1 REST API requires PrivateContents('FolderName') for private folder segments, but TM1py was always using Contents('FolderName') for intermediate path segments.
Solution: Implemented automatic path resolution with an optimistic probing strategy:
- Optimistic probing - Try all-public path first (most common case), then all-private path
- Fallback discovery - If both fail, iteratively probe each segment to find the exact public-to-private transition point
- Efficient probing - Uses $top=0 query parameter to probe paths without fetching actual data
- Optional caching - New use_cache parameter (default False) to cache discovered private boundaries for repeated access
- User warnings - Emits warnings when auto-resolution is used so users are aware of the path correction
Changes:
- Added _build_path_url() helper to construct URL paths with mixed Contents/PrivateContents segments
- Added _find_private_boundary() to iteratively discover where a path becomes private
- Added _resolve_path() that implements the optimistic probing strategy
- Updated all public methods (get_names, get, exists, delete, rename, create, update, etc.) to use path resolution
- Added use_cache parameter to all affected methods
- Added comprehensive unit tests for the new functionality
The optimistic approach is very sensible. I like it. The costs for the iterations are acceptable IMO.
However, I noticed that the new code breaks some tests that run fine in the master branch
I think the rename function requires some additional handling, as the URLs with tm1.Move extension don't support GET.
Summary
- Fixes #1317 - ApplicationService now correctly accesses applications inside private folders
- Added new
discover()method to explore the Applications folder hierarchy - Refactored path resolution to handle mixed public/private folder structures
New Features
discover() Method
Explore the Applications folder and discover all items including private assets:
# Discover all items at root level
items = tm1.applications.discover(path="", include_private=True)
# Discover recursively with nested structure
items = tm1.applications.discover(
path="Planning Sample",
include_private=True,
recursive=True,
flat=False # Returns nested structure with 'children' key
)
# Each item contains: @odata.type, type, id, name, path, is_private
Copy Private Document to Public Location
from TM1py import TM1Service
from TM1py.Objects.Application import DocumentApplication
with TM1Service(**params) as tm1:
# Get the private document
private_doc = tm1.applications.get_document(
path="Planning Sample/Administrator/PrivateFolder",
name="My Private Document",
private=True
)
# Create as public document
public_doc = DocumentApplication(
path="Planning Sample/Administrator",
name="My Public Document",
content=private_doc.content
)
tm1.applications.update_or_create(application=public_doc, private=False)
Access Documents in Nested Private Folders
# Now works correctly - previously failed with 404
doc = tm1.applications.get_document(
path="Planning Sample/Administrator/PrivateFolder/SubFolder",
name="Nested Document",
private=True
)
Test Plan
- [x] All existing ApplicationService tests pass
- [x] Added tests for
_build_path_url()with various boundary scenarios - [x] Added tests for
discover()(public, private, recursive, flat modes) - [x] Added tests for document operations in private folders
- [x] Added tests for nested private folder structures
- [x] Added tests for copying documents between private/public locations
Tests completed for environment: tm1-11-cloud. Check artifacts for details.