or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binding-specs.mddecorators.mderror-handling.mdfield-initialization.mdindex.mdobject-graph.mdscoping.md

field-initialization.mddocs/

0

# Field Initialization Utilities

1

2

Convenience decorators for automatically copying constructor arguments to instance fields, reducing boilerplate code in class initializers by eliminating manual field assignment.

3

4

## Capabilities

5

6

### Internal Field Copying

7

8

Automatically copies constructor arguments to private instance fields with underscore prefix.

9

10

```python { .api }

11

def copy_args_to_internal_fields(fn):

12

"""

13

Decorator that copies __init__ arguments to internal (private) fields.

14

15

Applies to __init__ methods only. Each argument 'arg_name' becomes '_arg_name' field.

16

Cannot be used with *args parameters.

17

18

Parameters:

19

- fn: __init__ method to decorate

20

21

Returns:

22

Decorated __init__ method that copies args to _field_name attributes

23

"""

24

```

25

26

### Public Field Copying

27

28

Automatically copies constructor arguments to public instance fields with same names.

29

30

```python { .api }

31

def copy_args_to_public_fields(fn):

32

"""

33

Decorator that copies __init__ arguments to public fields.

34

35

Applies to __init__ methods only. Each argument 'arg_name' becomes 'arg_name' field.

36

Cannot be used with *args parameters.

37

38

Parameters:

39

- fn: __init__ method to decorate

40

41

Returns:

42

Decorated __init__ method that copies args to field_name attributes

43

"""

44

```

45

46

## Usage Examples

47

48

### Internal Fields with Dependency Injection

49

50

```python

51

import pinject

52

53

class DatabaseConfig(object):

54

def __init__(self):

55

self.host = "localhost"

56

self.port = 5432

57

58

class UserRepository(object):

59

@pinject.copy_args_to_internal_fields

60

def __init__(self, database_config, table_name="users"):

61

# Arguments automatically copied to _database_config and _table_name

62

pass

63

64

def get_connection_info(self):

65

return f"Connecting to {self._database_config.host}:{self._database_config.port}"

66

67

def get_table(self):

68

return self._table_name

69

70

obj_graph = pinject.new_object_graph()

71

repo = obj_graph.provide(UserRepository) # uses default table_name="users"

72

73

print(repo.get_connection_info()) # "Connecting to localhost:5432"

74

print(repo.get_table()) # "users"

75

print(hasattr(repo, 'database_config')) # False (not public)

76

print(hasattr(repo, '_database_config')) # True (internal field)

77

```

78

79

### Public Fields with Manual Logic

80

81

```python

82

import pinject

83

84

class Logger(object):

85

def __init__(self):

86

self.level = "INFO"

87

88

class FileService(object):

89

@pinject.copy_args_to_public_fields

90

def __init__(self, logger, base_path="/tmp"):

91

# Arguments automatically copied to .logger and .base_path

92

# Additional initialization logic can follow

93

self.files_processed = 0

94

print(f"FileService initialized with path {self.base_path}")

95

96

def process_file(self, filename):

97

self.logger.level = "DEBUG"

98

full_path = f"{self.base_path}/{filename}"

99

self.files_processed += 1

100

return full_path

101

102

obj_graph = pinject.new_object_graph()

103

service = obj_graph.provide(FileService) # uses default base_path="/tmp"

104

105

print(service.logger.level) # "INFO" (initially)

106

path = service.process_file("test.txt")

107

print(path) # "/tmp/test.txt"

108

print(service.logger.level) # "DEBUG" (modified)

109

print(service.files_processed) # 1

110

```

111

112

### Combined with Other Decorators

113

114

```python

115

import pinject

116

117

class DatabaseConnection(object):

118

def __init__(self):

119

self.url = "postgresql://localhost"

120

121

class CacheService(object):

122

def __init__(self):

123

self.data = {}

124

125

class BusinessService(object):

126

@pinject.inject(['database_connection']) # Only inject database_connection

127

@pinject.copy_args_to_internal_fields # Copy all args to internal fields

128

def __init__(self, database_connection, cache_service, api_key):

129

# database_connection injected and copied to _database_connection

130

# cache_service passed directly and copied to _cache_service

131

# api_key passed directly and copied to _api_key

132

self.initialized = True

133

134

def get_data(self):

135

return {

136

'db_url': self._database_connection.url,

137

'cache_size': len(self._cache_service.data),

138

'api_key_length': len(self._api_key)

139

}

140

141

cache = CacheService()

142

cache.data['key1'] = 'value1'

143

144

obj_graph = pinject.new_object_graph()

145

service = obj_graph.provide(

146

BusinessService,

147

cache_service=cache,

148

api_key="secret123"

149

)

150

151

data = service.get_data()

152

print(data['db_url']) # "postgresql://localhost"

153

print(data['cache_size']) # 1

154

print(data['api_key_length']) # 9

155

```

156

157

### Error Handling

158

159

```python

160

import pinject

161

162

class InvalidDecoratorUsage(object):

163

# ERROR: copy_args decorators only work on __init__ methods

164

@pinject.copy_args_to_public_fields

165

def setup(self, config):

166

pass

167

168

class InvalidArgsUsage(object):

169

# ERROR: copy_args decorators don't work with *args

170

@pinject.copy_args_to_internal_fields

171

def __init__(self, service, *additional_args):

172

pass

173

174

# These will raise errors:

175

# - pinject.DecoratorAppliedToNonInitError for the first case

176

# - pinject.PargsDisallowedWhenCopyingArgsError for the second case

177

```

178

179

### Comparison: Manual vs Automatic Field Copying

180

181

```python

182

import pinject

183

184

# Manual approach (verbose)

185

class ManualService(object):

186

def __init__(self, database_service, cache_service, config):

187

self._database_service = database_service

188

self._cache_service = cache_service

189

self._config = config

190

# Additional initialization logic...

191

192

# Automatic approach (concise)

193

class AutoService(object):

194

@pinject.copy_args_to_internal_fields

195

def __init__(self, database_service, cache_service, config):

196

# Fields automatically created: _database_service, _cache_service, _config

197

# Focus on additional initialization logic only...

198

pass

199

200

# Both approaches result in identical field structure

201

obj_graph = pinject.new_object_graph()

202

manual = obj_graph.provide(ManualService)

203

auto = obj_graph.provide(AutoService)

204

205

print(hasattr(manual, '_database_service')) # True

206

print(hasattr(auto, '_database_service')) # True

207

```