or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdexceptions.mdhttp-operations.mdindex.mdnavigation.mdtemplated-links.mdutilities.md

templated-links.mddocs/

0

# Templated Links

1

2

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.

3

4

## Capabilities

5

6

### Template Navigation

7

8

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

9

10

```python { .api }

11

class PartialNavigator:

12

def __call__(self, **kwargs) -> 'HALNavigator':

13

"""

14

Expand template parameters to create a full HALNavigator.

15

16

Parameters:

17

- **kwargs: Template variable values

18

19

Returns:

20

HALNavigator for the expanded URI

21

"""

22

23

def expand_uri(self, **kwargs) -> str:

24

"""

25

Expand template to URI string without creating navigator.

26

27

Parameters:

28

- **kwargs: Template variable values

29

30

Returns:

31

Expanded URI string

32

"""

33

34

def expand_link(self, **kwargs) -> 'Link':

35

"""

36

Expand template to Link object.

37

38

Parameters:

39

- **kwargs: Template variable values

40

41

Returns:

42

Link object with expanded URI

43

"""

44

45

@property

46

def variables(self) -> set:

47

"""

48

Set of template variable names required for expansion.

49

50

Returns:

51

Set of variable names

52

"""

53

54

@property

55

def template_uri(self) -> str:

56

"""

57

The templated URI string before expansion.

58

59

Returns:

60

Original template URI

61

"""

62

```

63

64

### Template Discovery and Usage

65

66

```python

67

# Discover templated links

68

api_links = api.links()

69

user_template = api_links['ht:user'] # Returns PartialNavigator

70

71

# Check if it's a template

72

if hasattr(user_template, 'variables'):

73

print("Template variables:", user_template.variables)

74

print("Template URI:", user_template.template_uri)

75

76

# Expand template with parameters

77

user = user_template(name='john_doe')

78

79

# Alternative expansion methods

80

user_uri = user_template.expand_uri(name='john_doe')

81

user_link = user_template.expand_link(name='john_doe')

82

```

83

84

### Complex Template Examples

85

86

```python

87

# Single parameter template

88

# Template: "/users/{id}"

89

user = api['users'](id=123)

90

91

# Multiple parameter template

92

# Template: "/users/{id}/posts{?page,limit}"

93

posts = api['users'](id=123)['posts'](page=2, limit=10)

94

95

# Optional parameters (query strings)

96

# Template: "/search{?q,type,sort}"

97

search_results = api['search'](q='python', type='repositories')

98

99

# Complex template with path and query parameters

100

# Template: "/repos/{owner}/{repo}/issues{?state,labels,sort}"

101

issues = api['repos'](owner='octocat', repo='Hello-World')['issues'](

102

state='open',

103

labels='bug,enhancement',

104

sort='created'

105

)

106

```

107

108

### Template Validation and Error Handling

109

110

```python

111

# Check required variables before expansion

112

search_template = api['search']

113

required_vars = search_template.variables

114

print(f"Required parameters: {required_vars}")

115

116

# Partial expansion (providing only some parameters)

117

try:

118

# This might fail if 'q' is required

119

incomplete = api['search'](type='users') # Missing 'q' parameter

120

except Exception as e:

121

print("Template expansion error:", e)

122

123

# Safe expansion with validation

124

def safe_template_expand(template, **kwargs):

125

required = template.variables

126

provided = set(kwargs.keys())

127

missing = required - provided

128

129

if missing:

130

raise ValueError(f"Missing required parameters: {missing}")

131

132

return template(**kwargs)

133

134

# Usage

135

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

136

```

137

138

### Working with Template URIs

139

140

```python

141

# Get the raw template URI

142

template = api['users']

143

print("Template:", template.template_uri) # "/users/{id}"

144

145

# Expand to URI without creating navigator

146

user_uri = template.expand_uri(id=123) # "/users/123"

147

148

# Build full URL

149

full_url = api.session.base_url + user_uri

150

151

# Create Link object

152

link = template.expand_link(id=123)

153

print("Link URI:", link.uri)

154

print("Link properties:", link.props)

155

```

156

157

### Template Chaining

158

159

```python

160

# Chain templated navigations

161

user_posts = api['users'](id=123)['posts'](page=1)

162

163

# Equivalent to

164

user = api['users'](id=123)

165

posts = user['posts'](page=1)

166

167

# Mixed template and regular navigation

168

# api['users'](id=123)['posts', 'comments', 0]

169

specific_comment = api['users'](id=123)['posts']['comments'][0]

170

```

171

172

### Advanced Template Patterns

173

174

```python

175

# Store template for reuse

176

user_template = api['users']

177

178

# Create multiple users from same template

179

users = []

180

for user_id in [1, 2, 3, 4, 5]:

181

user = user_template(id=user_id)

182

users.append(user)

183

184

# Template with default values simulation

185

def get_user_posts(user_id, page=1, limit=20):

186

return api['users'](id=user_id)['posts'](page=page, limit=limit)

187

188

# Dynamic template parameter building

189

search_params = {'q': 'python'}

190

if include_forks:

191

search_params['fork'] = 'true'

192

if language:

193

search_params['language'] = language

194

195

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

196

```

197

198

### Template Inspection

199

200

```python

201

# Inspect all templated links in a resource

202

def find_templates(navigator):

203

templates = {}

204

for rel, link in navigator.links().items():

205

if hasattr(link, 'variables'):

206

templates[rel] = {

207

'uri': link.template_uri,

208

'variables': link.variables

209

}

210

return templates

211

212

# Usage

213

api_templates = find_templates(api)

214

for rel, info in api_templates.items():

215

print(f"{rel}: {info['uri']} (vars: {info['variables']})")

216

```