Skip to content

Conversation

@nicolasbisurgi
Copy link
Collaborator

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:

  1. Optimistic probing - Try all-public path first (most common case), then all-private path
  2. Fallback discovery - If both fail, iteratively probe each segment to find the exact public-to-private transition point
  3. Efficient probing - Uses $top=0 query parameter to probe paths without fetching actual data
  4. Optional caching - New use_cache parameter (default False) to cache discovered private boundaries for repeated access
  5. 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

@nicolasbisurgi nicolasbisurgi self-assigned this Nov 28, 2025
@nicolasbisurgi nicolasbisurgi added the release:patch Triggers patch version bump (e.g.: 1.4.9 → 1.4.10) label Nov 28, 2025
@MariusWirtz
Copy link
Collaborator

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.

image

…and discover()

This PR fixes issue #1317 where ApplicationService failed to access
applications inside private folders.

Key changes:
- Refactored _resolve_path() to properly handle mixed public/private
  folder hierarchies by probing path segments to find private boundaries
- Added _build_path_url() to construct correct URLs with PrivateContents
- Added _find_private_boundary() to detect where paths transition to private
- Added discover() method for exploring the Applications folder tree
- All application methods (get, get_document, exists, create, update,
  delete, rename) now correctly handle documents in private folders

The TM1 REST API requires different URL patterns:
- Public: /Contents('folder')/Contents('subfolder')
- Private: /PrivateContents('folder')/PrivateContents('subfolder')
- Mixed: /Contents('public')/PrivateContents('private')

Once inside a private folder, all nested content must use PrivateContents.
@nicolasbisurgi
Copy link
Collaborator Author

Summary

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

  • All existing ApplicationService tests pass
  • Added tests for _build_path_url() with various boundary scenarios
  • Added tests for discover() (public, private, recursive, flat modes)
  • Added tests for document operations in private folders
  • Added tests for nested private folder structures
  • Added tests for copying documents between private/public locations

@github-actions
Copy link
Contributor

Tests completed for environment: tm1-11-cloud. Check artifacts for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:patch Triggers patch version bump (e.g.: 1.4.9 → 1.4.10)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ApplicationService fails to access applications inside private folders

3 participants