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

ets-labs / python-dependency-injector / 15094271664

18 May 2025 08:54AM UTC coverage: 94.498% (-0.03%) from 94.523%
15094271664

push

github

ZipFile
Drop Python 3.7 support

2 of 2 new or added lines in 1 file covered. (100.0%)

14 existing lines in 4 files now uncovered.

3332 of 3526 relevant lines covered (94.5%)

0.94 hits per line

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

88.17
/src/dependency_injector/providers.pxd
1
"""Providers module."""
2

3
import asyncio
4
import functools
5

6
cimport cython
7

8

9
cdef int ASYNC_MODE_UNDEFINED
10
cdef int ASYNC_MODE_ENABLED
11
cdef int ASYNC_MODE_DISABLED
12

13
cdef set __iscoroutine_typecache
14
cdef tuple __COROUTINE_TYPES
15

16

17
# Base providers
18
cdef class Provider:
19
    cdef tuple _overridden
20
    cdef Provider _last_overriding
21
    cdef tuple _overrides
22
    cdef int _async_mode
23

24
    cpdef bint is_async_mode_enabled(self)
25
    cpdef bint is_async_mode_disabled(self)
26
    cpdef bint is_async_mode_undefined(self)
27

28
    cpdef object _provide(self, tuple args, dict kwargs)
29
    cpdef void _copy_overridings(self, Provider copied, dict memo)
30

31

32
cdef class Object(Provider):
33
    cdef object _provides
34

35
    cpdef object _provide(self, tuple args, dict kwargs)
36

37

38
cdef class Self(Provider):
39
    cdef object _container
40
    cdef tuple _alt_names
41

42

43
cdef class Delegate(Provider):
44
    cdef object _provides
45

46
    cpdef object _provide(self, tuple args, dict kwargs)
47

48

49
cdef class Aggregate(Provider):
50
    cdef dict _providers
51

52
    cdef Provider __get_provider(self, object provider_name)
53

54

55
cdef class Dependency(Provider):
56
    cdef object _instance_of
57
    cdef object _default
58
    cdef object _parent
59

60

61
cdef class ExternalDependency(Dependency):
62
    pass
63

64

65
cdef class DependenciesContainer(Object):
66
    cdef dict _providers
67
    cdef object _parent
68

69
    cpdef object _override_providers(self, object container)
70

71

72
# Callable providers
73
cdef class Callable(Provider):
74
    cdef object _provides
75

76
    cdef tuple _args
77
    cdef int _args_len
78

79
    cdef tuple _kwargs
80
    cdef int _kwargs_len
81

82
    cpdef object _provide(self, tuple args, dict kwargs)
83

84

85
cdef class DelegatedCallable(Callable):
86
    pass
87

88

89
cdef class AbstractCallable(Callable):
90
    cpdef object _provide(self, tuple args, dict kwargs)
91

92

93
cdef class CallableDelegate(Delegate):
94
    pass
95

96

97
# Coroutine providers
98
cdef class Coroutine(Callable):
99
    pass
100

101

102
cdef class DelegatedCoroutine(Coroutine):
103
    pass
104

105

106
cdef class AbstractCoroutine(Coroutine):
107
    cpdef object _provide(self, tuple args, dict kwargs)
108

109

110
cdef class CoroutineDelegate(Delegate):
111
    pass
112

113

114
# Configuration providers
115
cdef class ConfigurationOption(Provider):
116
    cdef tuple _name
117
    cdef Configuration _root
118
    cdef dict _children
119
    cdef bint _required
120
    cdef object _cache
121

122

123
cdef class TypedConfigurationOption(Callable):
124
    pass
125

126

127
cdef class Configuration(Object):
128
    cdef str _name
129
    cdef bint __strict
130
    cdef dict _children
131
    cdef list _ini_files
132
    cdef list _yaml_files
133
    cdef list _json_files
134
    cdef list _pydantic_settings
135
    cdef object __weakref__
136

137

138
# Factory providers
139
cdef class Factory(Provider):
140
    cdef Callable _instantiator
141

142
    cdef tuple _attributes
143
    cdef int _attributes_len
144

145
    cpdef object _provide(self, tuple args, dict kwargs)
146

147

148
cdef class DelegatedFactory(Factory):
149
    pass
150

151

152
cdef class AbstractFactory(Factory):
153
    cpdef object _provide(self, tuple args, dict kwargs)
154

155

156
cdef class FactoryDelegate(Delegate):
157
    pass
158

159

160
cdef class FactoryAggregate(Aggregate):
161
    pass
162

163

164
# Singleton providers
165
cdef class BaseSingleton(Provider):
166
    cdef Factory _instantiator
167
    cdef object _storage
168

169

170
cdef class Singleton(BaseSingleton):
171

172
    cpdef object _provide(self, tuple args, dict kwargs)
173

174

175
cdef class DelegatedSingleton(Singleton):
176
    pass
177

178

179
cdef class ThreadSafeSingleton(BaseSingleton):
180
    cdef object _storage_lock
181

182
    cpdef object _provide(self, tuple args, dict kwargs)
183

184

185
cdef class DelegatedThreadSafeSingleton(ThreadSafeSingleton):
186
    pass
187

188

189
cdef class ThreadLocalSingleton(BaseSingleton):
190

191
    cpdef object _provide(self, tuple args, dict kwargs)
192

193

194
cdef class ContextLocalSingleton(BaseSingleton):
195

196
    cpdef object _provide(self, tuple args, dict kwargs)
197

198

199
cdef class DelegatedThreadLocalSingleton(ThreadLocalSingleton):
200
    pass
201

202

203
cdef class AbstractSingleton(BaseSingleton):
204
    pass
205

206

207
cdef class SingletonDelegate(Delegate):
208
    pass
209

210

211
# Miscellaneous providers
212

213
cdef class List(Provider):
214
    cdef tuple _args
215
    cdef int _args_len
216

217
    cpdef object _provide(self, tuple args, dict kwargs)
218

219

220
cdef class Dict(Provider):
221
    cdef tuple _kwargs
222
    cdef int _kwargs_len
223

224
    cpdef object _provide(self, tuple args, dict kwargs)
225

226

227
cdef class Resource(Provider):
228
    cdef object _provides
229
    cdef bint _initialized
230
    cdef object _shutdowner
231
    cdef object _resource
232

233
    cdef tuple _args
234
    cdef int _args_len
235

236
    cdef tuple _kwargs
237
    cdef int _kwargs_len
238

239
    cpdef object _provide(self, tuple args, dict kwargs)
240

241

242
cdef class Container(Provider):
243
    cdef object _container_cls
244
    cdef dict _overriding_providers
245
    cdef object _container
246
    cdef object _parent
247

248
    cpdef object _provide(self, tuple args, dict kwargs)
249

250

251
cdef class Selector(Provider):
252
    cdef object _selector
253
    cdef dict _providers
254

255
    cpdef object _provide(self, tuple args, dict kwargs)
256

257
# Provided instance
258

259
cdef class ProvidedInstance(Provider):
260
    cdef object _provides
261

262
    cpdef object _provide(self, tuple args, dict kwargs)
263

264

265
cdef class AttributeGetter(Provider):
266
    cdef object _provides
267
    cdef object _name
268

269
    cpdef object _provide(self, tuple args, dict kwargs)
270

271

272
cdef class ItemGetter(Provider):
273
    cdef object _provides
274
    cdef object _name
275

276
    cpdef object _provide(self, tuple args, dict kwargs)
277

278

279
cdef class MethodCaller(Provider):
280
    cdef object _provides
281
    cdef tuple _args
282
    cdef int _args_len
283
    cdef tuple _kwargs
284
    cdef int _kwargs_len
285

286
    cpdef object _provide(self, tuple args, dict kwargs)
287

288

289
# Injections
290
cdef class Injection:
291
    cdef object _value
292
    cdef int _is_provider
293
    cdef int _is_delegated
294
    cdef int _call
295

296

297
cdef class PositionalInjection(Injection):
298
    pass
299

300

301
cdef class NamedInjection(Injection):
302
    cdef object _name
303

304

305
cpdef tuple parse_positional_injections(tuple args)
306

307

308
cpdef tuple parse_named_injections(dict kwargs)
309

310

311
# Utils
312
cdef class OverridingContext:
313
    cdef Provider _overridden
314
    cdef Provider _overriding
315

316

317
cdef class BaseSingletonResetContext:
318
    cdef object _singleton
319

320

321
cdef class SingletonResetContext(BaseSingletonResetContext):
322
    pass
323

324

325
cdef class SingletonFullResetContext(BaseSingletonResetContext):
326
    pass
327

328

329
cdef object CLASS_TYPES
330

331

332
cpdef bint is_provider(object instance)
333

334

335
cpdef object ensure_is_provider(object instance)
336

337

338
cpdef bint is_delegated(object instance)
339

340

341
cpdef str represent_provider(object provider, object provides)
342

343

344
cpdef bint is_container_instance(object instance)
345

346

347
cpdef bint is_container_class(object instance)
348

349

350
cpdef object deepcopy(object instance, dict memo=*)
351

352

353
# Inline helper functions
354
cdef inline object __get_name(NamedInjection self):
×
355
    return self._name
1✔
356

357

358
cdef inline object __get_value(Injection self):
×
359
    if self._call == 0:
1✔
360
        return self._value
1✔
361
    return self._value()
1✔
362

363

364
cdef inline object __get_value_kwargs(Injection self, dict kwargs):
×
365
    if self._call == 0:
1✔
366
        return self._value
×
367
    return self._value(**kwargs)
1✔
368

369

370
cdef inline tuple __separate_prefixed_kwargs(dict kwargs):
×
371
    cdef dict plain_kwargs = {}
1✔
372
    cdef dict prefixed_kwargs = {}
1✔
373

374
    for key, value in kwargs.items():
1✔
375
        if "__" not in key:
1✔
376
            plain_kwargs[key] = value
1✔
377
            continue
1✔
378

379
        index = key.index("__")
1✔
380
        prefix, name = key[:index], key[index+2:]
1✔
381

382
        if prefix not in prefixed_kwargs:
1✔
383
            prefixed_kwargs[prefix] = {}
1✔
384
        prefixed_kwargs[prefix][name] = value
1✔
385

386
    return plain_kwargs, prefixed_kwargs
1✔
387

388

UNCOV
389
@cython.boundscheck(False)
×
390
@cython.wraparound(False)
391
cdef inline object __provide_positional_args(
392
        tuple args,
393
        tuple inj_args,
394
        int inj_args_len,
395
        int async_mode,
396
):
397
    cdef int index
398
    cdef list positional_args = []
1✔
399
    cdef list future_args = []
1✔
400
    cdef PositionalInjection injection
401
    cdef object value
402

403
    if inj_args_len == 0:
1✔
404
        return args
1✔
405

406
    for index in range(inj_args_len):
1✔
407
        injection = <PositionalInjection>inj_args[index]
1✔
408
        value = __get_value(injection)
1✔
409
        positional_args.append(value)
1✔
410

411
        if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
1✔
412
            future_args.append((index, value))
1✔
413

414
    positional_args.extend(args)
1✔
415

416
    if future_args:
1✔
417
        return __combine_future_injections(positional_args, future_args)
1✔
418

419
    return positional_args
1✔
420

421

UNCOV
422
@cython.boundscheck(False)
×
423
@cython.wraparound(False)
424
cdef inline object __provide_keyword_args(
425
        dict kwargs,
426
        tuple inj_kwargs,
427
        int inj_kwargs_len,
428
        int async_mode,
429
):
430
    cdef int index
431
    cdef object name
432
    cdef object value
433
    cdef dict prefixed = {}
1✔
434
    cdef list future_kwargs = []
1✔
435
    cdef NamedInjection kw_injection
436

437
    if len(kwargs) == 0:
1✔
438
        for index in range(inj_kwargs_len):
1✔
439
            kw_injection = <NamedInjection>inj_kwargs[index]
1✔
440
            name = __get_name(kw_injection)
1✔
441
            value = __get_value(kw_injection)
1✔
442
            kwargs[name] = value
1✔
443
            if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
1✔
444
                future_kwargs.append((name, value))
1✔
445
    else:
446
        kwargs, prefixed = __separate_prefixed_kwargs(kwargs)
1✔
447

448

449
        for index in range(inj_kwargs_len):
1✔
450
            kw_injection = <NamedInjection>inj_kwargs[index]
1✔
451
            name = __get_name(kw_injection)
1✔
452

453
            if name in kwargs:
1✔
454
                continue
1✔
455

456
            if name in prefixed:
1✔
457
                value = __get_value_kwargs(kw_injection, prefixed[name])
1✔
458
            else:
459
                value = __get_value(kw_injection)
1✔
460

461
            kwargs[name] = value
1✔
462
            if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
1✔
463
                future_kwargs.append((name, value))
1✔
464

465
    if future_kwargs:
1✔
466
        return __combine_future_injections(kwargs, future_kwargs)
1✔
467

468
    return kwargs
1✔
469

470

471
cdef inline object __combine_future_injections(object injections, list future_injections):
×
472
    future_result = asyncio.Future()
1✔
473

474
    injections_ready = asyncio.gather(*[value for _, value in future_injections])
1✔
475
    injections_ready.add_done_callback(
1✔
476
        functools.partial(
1✔
477
            __async_prepare_args_kwargs_callback,
1✔
478
            future_result,
479
            injections,
480
            future_injections,
1✔
481
        ),
482
    )
483
    asyncio.ensure_future(injections_ready)
1✔
484

485
    return future_result
1✔
486

487

488
cdef inline void __async_prepare_args_kwargs_callback(
×
489
        object future_result,
490
        object args,
491
        object future_args_kwargs,
492
        object future,
493
):
494
    try:
1✔
495
        result = future.result()
1✔
496
        for value, (key, _) in zip(result, future_args_kwargs):
1✔
497
            args[key] = value
1✔
498
    except Exception as exception:
1✔
499
        future_result.set_exception(exception)
1✔
500
    else:
501
        future_result.set_result(args)
1✔
502

503

UNCOV
504
@cython.boundscheck(False)
×
505
@cython.wraparound(False)
506
cdef inline object __provide_attributes(tuple attributes, int attributes_len):
507
    cdef NamedInjection attr_injection
508
    cdef dict attribute_injections = {}
1✔
509
    cdef list future_attributes = []
1✔
510

511
    for index in range(attributes_len):
1✔
512
        attr_injection = <NamedInjection>attributes[index]
1✔
513
        name = __get_name(attr_injection)
1✔
514
        value = __get_value(attr_injection)
1✔
515
        attribute_injections[name] = value
1✔
516
        if __is_future_or_coroutine(value):
1✔
517
            future_attributes.append((name, value))
1✔
518

519
    if future_attributes:
1✔
520
        return __combine_future_injections(attribute_injections, future_attributes)
1✔
521

522
    return attribute_injections
1✔
523

524

525
cdef inline object __async_inject_attributes(future_instance, future_attributes):
×
526
    future_result = asyncio.Future()
1✔
527

528
    attributes_ready = asyncio.gather(future_instance, future_attributes)
1✔
529
    attributes_ready.add_done_callback(
1✔
530
        functools.partial(
1✔
531
            __async_inject_attributes_callback,
1✔
532
            future_result,
1✔
533
        ),
534
    )
535
    asyncio.ensure_future(attributes_ready)
1✔
536

537
    return future_result
1✔
538

539

540
cdef inline void __async_inject_attributes_callback(object future_result, object future):
×
541
    try:
1✔
542
        instance, attributes = future.result()
1✔
543

544
        for name, value in attributes.items():
1✔
545
            setattr(instance, name, value)
1✔
546
    except Exception as exception:
1✔
547
        future_result.set_exception(exception)
1✔
548
    else:
549
        future_result.set_result(instance)
1✔
550

551

552
cdef inline void __inject_attributes(object instance, dict attributes):
×
553
    for name, value in attributes.items():
1✔
554
        setattr(instance, name, value)
1✔
555

556

557
cdef inline object __call(
×
558
        object call,
559
        tuple context_args,
560
        tuple injection_args,
561
        int injection_args_len,
562
        dict context_kwargs,
563
        tuple injection_kwargs,
564
        int injection_kwargs_len,
565
        int async_mode,
566
):
567
    cdef object args = __provide_positional_args(
1✔
568
        context_args,
569
        injection_args,
570
        injection_args_len,
571
        async_mode,
572
    )
573
    cdef object kwargs = __provide_keyword_args(
1✔
574
        context_kwargs,
575
        injection_kwargs,
576
        injection_kwargs_len,
577
        async_mode,
578
    )
579

580
    if async_mode == ASYNC_MODE_DISABLED:
1✔
581
        return call(*args, **kwargs)
1✔
582

583
    cdef bint is_future_args = __is_future_or_coroutine(args)
1✔
584
    cdef bint is_future_kwargs = __is_future_or_coroutine(kwargs)
1✔
585

586
    if is_future_args or is_future_kwargs:
1✔
587
        future_args = args if is_future_args else __future_result(args)
1✔
588
        future_kwargs = kwargs if is_future_kwargs else __future_result(kwargs)
1✔
589

590
        future_result = asyncio.Future()
1✔
591

592
        args_kwargs_ready = asyncio.gather(future_args, future_kwargs)
1✔
593
        args_kwargs_ready.add_done_callback(
1✔
594
            functools.partial(
1✔
595
                __async_call_callback,
1✔
596
                future_result,
597
                call,
1✔
598
            ),
599
        )
600
        asyncio.ensure_future(args_kwargs_ready)
1✔
601

602
        return future_result
1✔
603

604
    return call(*args, **kwargs)
1✔
605

606

607
cdef inline void __async_call_callback(object future_result, object call, object future):
×
608
    try:
1✔
609
        args, kwargs = future.result()
1✔
610
        result = call(*args, **kwargs)
1✔
611
    except Exception as exception:
1✔
612
        future_result.set_exception(exception)
1✔
613
    else:
614
        if __is_future_or_coroutine(result):
1✔
615
            result = asyncio.ensure_future(result)
1✔
616
            result.add_done_callback(functools.partial(__async_result_callback, future_result))
1✔
617
            return
1✔
618
        future_result.set_result(result)
1✔
619

620

621
cdef inline object __async_result_callback(object future_result, object future):
×
622
    try:
1✔
623
        result = future.result()
1✔
624
    except Exception as exception:
1✔
625
        future_result.set_exception(exception)
1✔
626
    else:
627
        future_result.set_result(result)
1✔
628

629

630
cdef inline object __callable_call(Callable self, tuple args, dict kwargs, ):
×
631
    return __call(
1✔
632
        self._provides,
1✔
633
        args,
634
        self._args,
1✔
635
        self._args_len,
636
        kwargs,
637
        self._kwargs,
1✔
638
        self._kwargs_len,
639
        self._async_mode,
640
    )
641

642

643
cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
×
644
    cdef object instance
645

646
    instance = __call(
1✔
647
        self._instantiator._provides,
1✔
648
        args,
649
        self._instantiator._args,
1✔
650
        self._instantiator._args_len,
651
        kwargs,
652
        self._instantiator._kwargs,
1✔
653
        self._instantiator._kwargs_len,
654
        self._async_mode,
655
    )
656

657
    if self._attributes_len > 0:
1✔
658
        attributes = __provide_attributes(self._attributes, self._attributes_len)
1✔
659

660
        is_future_instance = __is_future_or_coroutine(instance)
1✔
661
        is_future_attributes = __is_future_or_coroutine(attributes)
1✔
662

663
        if is_future_instance or is_future_attributes:
1✔
664
            future_instance = instance if is_future_instance else __future_result(instance)
1✔
665
            future_attributes = attributes if is_future_attributes else __future_result(attributes)
1✔
666
            return __async_inject_attributes(future_instance, future_attributes)
1✔
667

668
        __inject_attributes(instance, attributes)
1✔
669

670
    return instance
1✔
671

672

673
cdef inline bint __is_future_or_coroutine(object instance):
×
674
    return __isfuture(instance) or __iscoroutine(instance)
1✔
675

676

677
cdef inline bint __isfuture(object obj):
×
678
    return hasattr(obj.__class__, "_asyncio_future_blocking") and obj._asyncio_future_blocking is not None
1✔
679

680

681
cdef inline bint __iscoroutine(object obj):
×
682
    if type(obj) in __iscoroutine_typecache:
1✔
683
        return True
1✔
684

685
    if isinstance(obj, __COROUTINE_TYPES):
1✔
686
        # Just in case we don't want to cache more than 100
687
        # positive types.  That shouldn't ever happen, unless
688
        # someone stressing the system on purpose.
689
        if len(__iscoroutine_typecache) < 100:
1✔
690
            __iscoroutine_typecache.add(type(obj))
1✔
691
        return True
1✔
692
    else:
693
        return False
1✔
694

695

696
cdef inline object __future_result(object instance):
×
697
    future_result = asyncio.Future()
1✔
698
    future_result.set_result(instance)
1✔
699
    return future_result
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