0
# Binding Specifications
1
2
Custom binding configuration through BindingSpec classes that define explicit relationships between interfaces and implementations, enabling complex dependency scenarios beyond automatic resolution.
3
4
## Capabilities
5
6
### BindingSpec Base Class
7
8
Abstract base class for creating custom binding specifications that define how dependencies should be resolved.
9
10
```python { .api }
11
class BindingSpec(object):
12
def configure(self, bind):
13
"""
14
Configures bindings for the object graph.
15
16
Parameters:
17
- bind: binding configuration object for creating explicit bindings
18
19
Called by the object graph during initialization to register custom bindings.
20
"""
21
```
22
23
### Binding Configuration Methods
24
25
Methods available within BindingSpec.configure() for defining explicit bindings.
26
27
```python { .api }
28
class Binder(object):
29
def __call__(self, binding_key):
30
"""
31
Creates a binding for the specified key.
32
33
Parameters:
34
- binding_key: key to bind (typically a string matching parameter name)
35
36
Returns:
37
Binding configuration object with to_class(), to_instance(), and to_provider() methods
38
"""
39
40
def to_class(self, cls, in_scope=None):
41
"""
42
Binds to a specific class.
43
44
Parameters:
45
- cls: class to instantiate for this binding
46
- in_scope: scope ID for instances (SINGLETON, PROTOTYPE, or custom)
47
"""
48
49
def to_instance(self, instance):
50
"""
51
Binds to a specific instance.
52
53
Parameters:
54
- instance: pre-created instance to use for this binding
55
"""
56
57
def to_provider(self, provider_fn, in_scope=None):
58
"""
59
Binds to a provider function.
60
61
Parameters:
62
- provider_fn: function that returns instances for this binding
63
- in_scope: scope ID for instances
64
"""
65
```
66
67
## Usage Examples
68
69
### Basic Binding Specification
70
71
```python
72
import pinject
73
74
class DatabaseInterface(object):
75
pass
76
77
class PostgreSQLDatabase(DatabaseInterface):
78
def __init__(self):
79
self.connection = "postgresql://localhost"
80
81
class MySQLDatabase(DatabaseInterface):
82
def __init__(self):
83
self.connection = "mysql://localhost"
84
85
class DatabaseBindingSpec(pinject.BindingSpec):
86
def configure(self, bind):
87
# Bind interface to specific implementation
88
bind('database_interface').to_class(PostgreSQLDatabase)
89
90
class UserService(object):
91
def __init__(self, database_interface):
92
self.db = database_interface
93
94
obj_graph = pinject.new_object_graph(binding_specs=[DatabaseBindingSpec()])
95
user_service = obj_graph.provide(UserService)
96
print(user_service.db.connection) # "postgresql://localhost"
97
```
98
99
### Instance Bindings
100
101
```python
102
import pinject
103
104
class Configuration(object):
105
def __init__(self, env, debug):
106
self.environment = env
107
self.debug_mode = debug
108
109
class ConfigBindingSpec(pinject.BindingSpec):
110
def configure(self, bind):
111
# Bind to pre-created instances
112
prod_config = Configuration('production', False)
113
bind('configuration').to_instance(prod_config)
114
115
class AppService(object):
116
def __init__(self, configuration):
117
self.config = configuration
118
119
obj_graph = pinject.new_object_graph(binding_specs=[ConfigBindingSpec()])
120
app = obj_graph.provide(AppService)
121
print(app.config.environment) # "production"
122
```
123
124
### Provider Function Bindings
125
126
```python
127
import pinject
128
import logging
129
130
class LoggingBindingSpec(pinject.BindingSpec):
131
def configure(self, bind):
132
# Bind to provider functions
133
bind('logger').to_provider(self._create_logger, in_scope=pinject.SINGLETON)
134
bind('file_handler').to_provider(lambda: logging.FileHandler('app.log'))
135
136
def _create_logger(self, file_handler):
137
logger = logging.getLogger('myapp')
138
logger.addHandler(file_handler)
139
logger.setLevel(logging.INFO)
140
return logger
141
142
class AppService(object):
143
def __init__(self, logger):
144
self.logger = logger
145
146
obj_graph = pinject.new_object_graph(binding_specs=[LoggingBindingSpec()])
147
app = obj_graph.provide(AppService)
148
app.logger.info("Application started")
149
```
150
151
### Scoped Bindings
152
153
```python
154
import pinject
155
156
class DatabaseConnection(object):
157
def __init__(self):
158
self.connection_id = id(self)
159
160
class ConnectionBindingSpec(pinject.BindingSpec):
161
def configure(self, bind):
162
# Singleton: same instance shared across the application
163
bind('shared_connection').to_class(DatabaseConnection, in_scope=pinject.SINGLETON)
164
165
# Prototype: new instance every time
166
bind('temp_connection').to_class(DatabaseConnection, in_scope=pinject.PROTOTYPE)
167
168
class ServiceA(object):
169
def __init__(self, shared_connection, temp_connection):
170
self.shared = shared_connection
171
self.temp = temp_connection
172
173
class ServiceB(object):
174
def __init__(self, shared_connection, temp_connection):
175
self.shared = shared_connection
176
self.temp = temp_connection
177
178
obj_graph = pinject.new_object_graph(binding_specs=[ConnectionBindingSpec()])
179
service_a = obj_graph.provide(ServiceA)
180
service_b = obj_graph.provide(ServiceB)
181
182
# Shared connections are the same instance
183
print(service_a.shared.connection_id == service_b.shared.connection_id) # True
184
185
# Temp connections are different instances
186
print(service_a.temp.connection_id == service_b.temp.connection_id) # False
187
```
188
189
### Provider Methods with Dependencies
190
191
```python
192
import pinject
193
194
class DatabaseConfig(object):
195
def __init__(self):
196
self.host = "localhost"
197
self.port = 5432
198
199
class DatabaseConnection(object):
200
def __init__(self, host, port):
201
self.host = host
202
self.port = port
203
204
class DatabaseBindingSpec(pinject.BindingSpec):
205
def configure(self, bind):
206
bind('database_config').to_class(DatabaseConfig)
207
bind('database_connection').to_provider(self._create_connection)
208
209
def _create_connection(self, database_config):
210
# Provider methods can have their own dependencies injected
211
return DatabaseConnection(database_config.host, database_config.port)
212
213
obj_graph = pinject.new_object_graph(binding_specs=[DatabaseBindingSpec()])
214
connection = obj_graph.provide(DatabaseConnection)
215
```