CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-restnavigator

A python library for interacting with HAL+JSON APIs

Pending
Overview
Eval results
Files

templated-links.mddocs/

Templated Links

Support for HAL templated links with parameter expansion and URI template processing. RestNavigator handles RFC 6570 URI templates transparently, allowing dynamic URL construction from templates.

Capabilities

Template Navigation

Navigate templated links by providing required parameters to expand URLs dynamically.

class PartialNavigator:
    def __call__(self, **kwargs) -> 'HALNavigator':
        """
        Expand template parameters to create a full HALNavigator.
        
        Parameters:
        - **kwargs: Template variable values
        
        Returns:
        HALNavigator for the expanded URI
        """
    
    def expand_uri(self, **kwargs) -> str:
        """
        Expand template to URI string without creating navigator.
        
        Parameters:
        - **kwargs: Template variable values
        
        Returns:
        Expanded URI string
        """
    
    def expand_link(self, **kwargs) -> 'Link':
        """
        Expand template to Link object.
        
        Parameters:
        - **kwargs: Template variable values
        
        Returns:
        Link object with expanded URI
        """
    
    @property
    def variables(self) -> set:
        """
        Set of template variable names required for expansion.
        
        Returns:
        Set of variable names
        """
    
    @property
    def template_uri(self) -> str:
        """
        The templated URI string before expansion.
        
        Returns:
        Original template URI
        """

Template Discovery and Usage

# Discover templated links
api_links = api.links()
user_template = api_links['ht:user']  # Returns PartialNavigator

# Check if it's a template
if hasattr(user_template, 'variables'):
    print("Template variables:", user_template.variables)
    print("Template URI:", user_template.template_uri)

# Expand template with parameters
user = user_template(name='john_doe')

# Alternative expansion methods
user_uri = user_template.expand_uri(name='john_doe')
user_link = user_template.expand_link(name='john_doe')

Complex Template Examples

# Single parameter template
# Template: "/users/{id}"
user = api['users'](id=123)

# Multiple parameter template  
# Template: "/users/{id}/posts{?page,limit}"
posts = api['users'](id=123)['posts'](page=2, limit=10)

# Optional parameters (query strings)
# Template: "/search{?q,type,sort}"
search_results = api['search'](q='python', type='repositories')

# Complex template with path and query parameters
# Template: "/repos/{owner}/{repo}/issues{?state,labels,sort}"
issues = api['repos'](owner='octocat', repo='Hello-World')['issues'](
    state='open',
    labels='bug,enhancement',
    sort='created'
)

Template Validation and Error Handling

# Check required variables before expansion
search_template = api['search']
required_vars = search_template.variables
print(f"Required parameters: {required_vars}")

# Partial expansion (providing only some parameters)
try:
    # This might fail if 'q' is required
    incomplete = api['search'](type='users')  # Missing 'q' parameter
except Exception as e:
    print("Template expansion error:", e)

# Safe expansion with validation
def safe_template_expand(template, **kwargs):
    required = template.variables
    provided = set(kwargs.keys())
    missing = required - provided
    
    if missing:
        raise ValueError(f"Missing required parameters: {missing}")
    
    return template(**kwargs)

# Usage
user = safe_template_expand(api['users'], id=123)

Working with Template URIs

# Get the raw template URI
template = api['users']
print("Template:", template.template_uri)  # "/users/{id}"

# Expand to URI without creating navigator
user_uri = template.expand_uri(id=123)  # "/users/123"

# Build full URL
full_url = api.session.base_url + user_uri

# Create Link object
link = template.expand_link(id=123)
print("Link URI:", link.uri)
print("Link properties:", link.props)

Template Chaining

# Chain templated navigations
user_posts = api['users'](id=123)['posts'](page=1)

# Equivalent to
user = api['users'](id=123)
posts = user['posts'](page=1)

# Mixed template and regular navigation
# api['users'](id=123)['posts', 'comments', 0]
specific_comment = api['users'](id=123)['posts']['comments'][0]

Advanced Template Patterns

# Store template for reuse
user_template = api['users']

# Create multiple users from same template
users = []
for user_id in [1, 2, 3, 4, 5]:
    user = user_template(id=user_id)
    users.append(user)

# Template with default values simulation
def get_user_posts(user_id, page=1, limit=20):
    return api['users'](id=user_id)['posts'](page=page, limit=limit)

# Dynamic template parameter building
search_params = {'q': 'python'}
if include_forks:
    search_params['fork'] = 'true'
if language:
    search_params['language'] = language

results = api['search'](**search_params)

Template Inspection

# Inspect all templated links in a resource
def find_templates(navigator):
    templates = {}
    for rel, link in navigator.links().items():
        if hasattr(link, 'variables'):
            templates[rel] = {
                'uri': link.template_uri,
                'variables': link.variables
            }
    return templates

# Usage
api_templates = find_templates(api)
for rel, info in api_templates.items():
    print(f"{rel}: {info['uri']} (vars: {info['variables']})")

Install with Tessl CLI

npx tessl i tessl/pypi-restnavigator

docs

authentication.md

exceptions.md

http-operations.md

index.md

navigation.md

templated-links.md

utilities.md

tile.json