• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / zope.component / 15267835484

27 May 2025 06:07AM UTC coverage: 99.774%. Remained the same
15267835484

Pull #76

github

web-flow
Trigger CI
Pull Request #76: Add preliminary support for Python 3.14

241 of 252 branches covered (95.63%)

Branch coverage included in aggregate %.

4615 of 4615 relevant lines covered (100.0%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/zope/component/interfaces.py
1
############################################################################
2
#
3
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
############################################################################
14
"""
15
Component and Component Architecture Interfaces
16

17
The `IComponentArchitecture` and `IComponentRegistrationConvenience` interfaces
18
are provided by `zope.component` directly.
19
"""
20
from zope.interface import Attribute
1✔
21
from zope.interface import Interface
1✔
22

23

24
# pylint:disable=inherit-non-class,no-self-argument,no-method-argument
25

26
class IComponentArchitecture(Interface):
1✔
27
    """The Component Architecture is defined by two key components: Adapters
28
    and Utiltities. Both are managed by site managers. All other components
29
    build on top of them.
30
    """
31
    # Site Manager API
32

33
    def getGlobalSiteManager():
1✔
34
        """Return the global site manager.
35

36
        This function should never fail and always return an object that
37
        provides `zope.interface.interfaces.IComponents`.
38
        """
39

40
    def getSiteManager(context=None):
1✔
41
        """Get the nearest site manager in the given context.
42

43
        If *context* is `None`, return the global site manager.
44

45
        If the *context* is not `None`, it is expected that an adapter
46
        from the *context* to
47
        :mod:`zope.interface.interfaces.IComponentLookup` can be
48
        found. If no adapter is found, a
49
        `~zope.interface.interfaces.ComponentLookupError` is raised.
50
        """
51

52
    # Utility API
53

54
    def getUtility(interface, name='', context=None):
1✔
55
        """Get the utility that provides interface
56

57
        Returns the nearest utility to the context that implements the
58
        specified interface. If one is not found, raises
59
        `~zope.interface.interfaces.ComponentLookupError`.
60
        """
61

62
    def queryUtility(interface, name='', default=None, context=None):
1✔
63
        """Look for the utility that provides *interface*
64

65
        Returns the nearest utility to the *context* that implements the
66
        specified interface. If one is not found, returns *default*.
67
        """
68

69
    def queryNextUtility(context, interface, name='', default=None):
1✔
70
        """Query for the next available utility.
71

72
        Find the next available utility providing *interface* and having the
73
        specified name. If no utility was found, return the specified *default*
74
        value.
75
        """
76

77
    def getNextUtility(context, interface, name=''):
1✔
78
        """Get the next available utility.
79

80
        If no utility was found, a
81
        `~zope.interface.interfaces.ComponentLookupError` is raised.
82
        """
83

84
    def getUtilitiesFor(interface, context=None):
1✔
85
        """Return the utilities that provide an interface
86

87
        An iterable of utility name-value pairs is returned.
88
        """
89

90
    def getAllUtilitiesRegisteredFor(interface, context=None):
1✔
91
        """Return all registered utilities for an interface
92

93
        This includes overridden utilities.
94

95
        An iterable of utility instances is returned.  No names are
96
        returned.
97
        """
98

99
    # Adapter API
100

101
    def getAdapter(object,
1✔
102
                   interface=Interface, name='',
103
                   context=None):
104
        """Get a named adapter to an interface for an object
105

106
        Returns an adapter that can adapt object to interface.  If a matching
107
        adapter cannot be found, raises
108
        `~zope.interface.interfaces.ComponentLookupError`.
109
        """
110

111
    def getAdapterInContext(object, interface, context):
1✔
112
        """Get a special adapter to an interface for an object
113

114
        .. note::
115
            This method should only be used if a custom context
116
            needs to be provided to provide custom component
117
            lookup. Otherwise, call the interface, as in::
118

119
               interface(object)
120

121
        Returns an adapter that can adapt object to interface. If a
122
        matching adapter cannot be found, raises
123
        `~zope.interface.interfaces.ComponentLookupError`.
124

125
        If the object has a ``__conform__`` method, this method will be
126
        called with the requested interface. If the method returns a
127
        non-None value, that value will be returned. Otherwise, if the
128
        object already implements the interface, the object will be
129
        returned.
130
        """
131

132
    def getMultiAdapter(objects,
1✔
133
                        interface=Interface, name='',
134
                        context=None):
135
        """Look for a multi-adapter to an *interface* for an *objects*
136

137
        Returns a multi-adapter that can adapt *objects* to *interface*.
138
        If a matching adapter cannot be found, raises
139
        `~zope.interface.interfaces.ComponentLookupError`.
140

141
        The name consisting of an empty string is reserved for unnamed
142
        adapters. The unnamed adapter methods will often call the
143
        named adapter methods with an empty string for a name.
144
        """
145

146
    def queryAdapter(object, interface=Interface, name='',
1✔
147
                     default=None, context=None):
148
        """Look for a named adapter to an interface for an object
149

150
        Returns an adapter that can adapt object to interface. If a
151
        matching adapter cannot be found, returns the default.
152
        """
153

154
    def queryAdapterInContext(object, interface, context, default=None):
1✔
155
        """
156
        Look for a special adapter to an interface for an object
157

158
        .. note::
159

160
            This method should only be used if a custom context
161
            needs to be provided to provide custom component lookup.
162
            Otherwise, call the interface, as in::
163

164
                interface(object, default)
165

166
        Returns an adapter that can adapt object to interface. If a
167
        matching adapter cannot be found, returns the default.
168

169
        If the object has a ``__conform__`` method, this method will be
170
        called with the requested interface. If the method returns a
171
        non-None value, that value will be returned. Otherwise, if the
172
        object already implements the interface, the object will be
173
        returned.
174
        """
175

176
    def queryMultiAdapter(objects,
1✔
177
                          interface=Interface, name='',
178
                          default=None,
179
                          context=None):
180
        """Look for a multi-adapter to an interface for objects
181

182
        Returns a multi-adapter that can adapt objects to interface.  If a
183
        matching adapter cannot be found, returns the default.
184

185
        The name consisting of an empty string is reserved for unnamed
186
        adapters. The unnamed adapter methods will often call the
187
        named adapter methods with an empty string for a name.
188
        """
189

190
    def getAdapters(objects, provided, context=None):
1✔
191
        """
192
        Look for all matching adapters to a provided interface for
193
        objects
194

195
        Return a list of adapters that match. If an adapter is named,
196
        only the most specific adapter of a given name is returned.
197
        """
198

199
    def subscribers(required, provided, context=None):
1✔
200
        """Get subscribers
201

202
        Subscribers are returned that provide the provided interface
203
        and that depend on and are computed from the sequence of
204
        required objects.
205
        """
206

207
    def handle(*objects):
1✔
208
        """Call all of the handlers for the given objects
209

210
        Handlers are subscription adapter factories that don't produce
211
        anything. They do all of their work when called. Handlers are
212
        typically used to handle events.
213
        """
214

215
    def adapts(*interfaces):
1✔
216
        """
217
        Declare that a class adapts the given interfaces.
218

219
        This function can only be used in a class definition.
220

221
        (TODO, allow classes to be passed as well as interfaces.)
222
        """
223

224
    # Factory service
225

226
    def createObject(factory_name, *args, **kwargs):
1✔
227
        """Create an object using a factory
228

229
        Finds the named factory in the current site and calls it with
230
        the given arguments. If a matching factory cannot be found
231
        raises `~zope.interface.interfaces.ComponentLookupError`.
232
        Returns the created object.
233

234
        A context keyword argument can be provided to cause the
235
        factory to be looked up in a location other than the current
236
        site. (Of course, this means that it is impossible to pass a
237
        keyword argument named "context" to the factory.
238
        """
239

240
    def getFactoryInterfaces(name, context=None):
1✔
241
        """Get interfaces implemented by a factory
242

243
        Finds the factory of the given name that is nearest to the
244
        context, and returns the interface or interface tuple that
245
        object instances created by the named factory will implement.
246
        """
247

248
    def getFactoriesFor(interface, context=None):
1✔
249
        """Return a tuple (name, factory) of registered factories that
250
        create objects which implement the given interface.
251
        """
252

253

254
class IRegistry(Interface):
1✔
255
    """Object that supports component registry
256
    """
257

258
    def registrations():
1✔
259
        """Return an iterable of component registrations
260
        """
261

262

263
class IComponentRegistrationConvenience(Interface):
1✔
264
    """API for registering components.
265

266
    .. caution::
267
        This API should only be used from test or
268
        application-setup code. This api shouldn't be used by regular
269
        library modules, as component registration is a configuration
270
        activity.
271
    """
272

273
    def provideUtility(component, provides=None, name=''):
1✔
274
        """Register a utility globally
275

276
        A utility is registered to provide an interface with a
277
        name. If a component provides only one interface, then the
278
        provides argument can be omitted and the provided interface
279
        will be used. (In this case, provides argument can still be
280
        provided to provide a less specific interface.)
281
        """
282

283
    def provideAdapter(factory, adapts=None, provides=None, name=''):
1✔
284
        """Register an adapter globally
285

286
        An adapter is registered to provide an interface with a name
287
        for some number of object types. If a factory implements only
288
        one interface, then the provides argument can be omitted and
289
        the provided interface will be used. (In this case, a provides
290
        argument can still be provided to provide a less specific
291
        interface.)
292

293
        If the factory has an adapts declaration, then the adapts
294
        argument can be omitted and the declaration will be used.  (An
295
        adapts argument can be provided to override the declaration.)
296
        """
297

298
    def provideSubscriptionAdapter(factory, adapts=None, provides=None):
1✔
299
        """Register a subscription adapter
300

301
        A subscription adapter is registered to provide an interface
302
        for some number of object types. If a factory implements only
303
        one interface, then the provides argument can be omitted and
304
        the provided interface will be used. (In this case, a provides
305
        argument can still be provided to provide a less specific
306
        interface.)
307

308
        If the factory has an adapts declaration, then the adapts
309
        argument can be omitted and the declaration will be used.  (An
310
        adapts argument can be provided to override the declaration.)
311
        """
312

313
    def provideHandler(handler, adapts=None):
1✔
314
        """Register a handler
315

316
        Handlers are subscription adapter factories that don't produce
317
        anything.  They do all of their work when called.  Handlers
318
        are typically used to handle events.
319

320
        If the handler has an adapts declaration, then the adapts
321
        argument can be omitted and the declaration will be used.  (An
322
        adapts argument can be provided to override the declaration.)
323
        """
324

325

326
class IPossibleSite(Interface):
1✔
327
    """An object that could be a site.
328
    """
329

330
    def setSiteManager(sitemanager):
1✔
331
        """Sets the site manager for this object.
332
        """
333

334
    def getSiteManager():
1✔
335
        """Returns the site manager contained in this object.
336

337
        If there isn't a site manager, raise a component lookup.
338
        """
339

340

341
class ISite(IPossibleSite):
1✔
342
    """Marker interface to indicate that we have a site"""
343

344

345
class Misused(Exception):
1✔
346
    """A component is being used (registered) for the wrong interface."""
347

348

349
class IFactory(Interface):
1✔
350
    """A factory is responsible for creating other components."""
351

352
    title = Attribute("The factory title.")
1✔
353

354
    description = Attribute("A brief description of the factory.")
1✔
355

356
    def __call__(*args, **kw):
1✔
357
        """Return an instance of the objects we're a factory for."""
358

359
    def getInterfaces():
1✔
360
        """Get the interfaces implemented by the factory
361

362
        Return the interface(s), as an instance of Implements, that objects
363
        created by this factory will implement. If the callable's Implements
364
        instance cannot be created, an empty Implements instance is returned.
365
        """
366

367

368
# Internal helpers
369

370
def _inherits_docs(func, iface):
1✔
371
    doc = iface[func.__name__].__doc__
1✔
372

373
    # doc can be None if the interpreter drops all docstrings when the
374
    # environment variable PYTHONOPTIMIZE is set 2.
375
    if doc is None:
1✔
376
        return func  # pragma: no cover
377

378
    # By adding the ..seealso:: we get a link from our overview page
379
    # to the specific narrative place where the function is described, because
380
    # our overview page uses :noindex:
381
    doc += "\n        .. seealso::"
1✔
382
    doc += f"\n           Function `~zope.component.{func.__name__}` for"
1✔
383
    doc += " notes, and "
1✔
384
    doc += f"\n           `~zope.component.interfaces.{iface.__name__}` for"
1✔
385
    doc += " the defining interface.\n"
1✔
386
    func.__doc__ = doc
1✔
387
    return func
1✔
388

389

390
def inherits_arch_docs(func):
1✔
391
    return _inherits_docs(func, IComponentArchitecture)
1✔
392

393

394
def inherits_reg_docs(func):
1✔
395
    return _inherits_docs(func, IComponentRegistrationConvenience)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc