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

ets-labs / python-dependency-injector / 13485278265

23 Feb 2025 05:22PM UTC coverage: 93.883%. Remained the same
13485278265

push

github

ZipFile
Bump version to v4.46.0

3361 of 3580 relevant lines covered (93.88%)

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
try:
4
    import asyncio
5
except ImportError:
6
    asyncio = None
7

8
import functools
9

10
cimport cython
11

12

13
cdef int ASYNC_MODE_UNDEFINED
14
cdef int ASYNC_MODE_ENABLED
15
cdef int ASYNC_MODE_DISABLED
16

17
cdef set __iscoroutine_typecache
18
cdef tuple __COROUTINE_TYPES
19

20

21
# Base providers
22
cdef class Provider(object):
23
    cdef tuple _overridden
24
    cdef Provider _last_overriding
25
    cdef tuple _overrides
26
    cdef int _async_mode
27

28
    cpdef bint is_async_mode_enabled(self)
29
    cpdef bint is_async_mode_disabled(self)
30
    cpdef bint is_async_mode_undefined(self)
31

32
    cpdef object _provide(self, tuple args, dict kwargs)
33
    cpdef void _copy_overridings(self, Provider copied, dict memo)
34

35

36
cdef class Object(Provider):
37
    cdef object _provides
38

39
    cpdef object _provide(self, tuple args, dict kwargs)
40

41

42
cdef class Self(Provider):
43
    cdef object _container
44
    cdef tuple _alt_names
45

46

47
cdef class Delegate(Provider):
48
    cdef object _provides
49

50
    cpdef object _provide(self, tuple args, dict kwargs)
51

52

53
cdef class Aggregate(Provider):
54
    cdef dict _providers
55

56
    cdef Provider __get_provider(self, object provider_name)
57

58

59
cdef class Dependency(Provider):
60
    cdef object _instance_of
61
    cdef object _default
62
    cdef object _parent
63

64

65
cdef class ExternalDependency(Dependency):
66
    pass
67

68

69
cdef class DependenciesContainer(Object):
70
    cdef dict _providers
71
    cdef object _parent
72

73
    cpdef object _override_providers(self, object container)
74

75

76
# Callable providers
77
cdef class Callable(Provider):
78
    cdef object _provides
79

80
    cdef tuple _args
81
    cdef int _args_len
82

83
    cdef tuple _kwargs
84
    cdef int _kwargs_len
85

86
    cpdef object _provide(self, tuple args, dict kwargs)
87

88

89
cdef class DelegatedCallable(Callable):
90
    pass
91

92

93
cdef class AbstractCallable(Callable):
94
    cpdef object _provide(self, tuple args, dict kwargs)
95

96

97
cdef class CallableDelegate(Delegate):
98
    pass
99

100

101
# Coroutine providers
102
cdef class Coroutine(Callable):
103
    pass
104

105

106
cdef class DelegatedCoroutine(Coroutine):
107
    pass
108

109

110
cdef class AbstractCoroutine(Coroutine):
111
    cpdef object _provide(self, tuple args, dict kwargs)
112

113

114
cdef class CoroutineDelegate(Delegate):
115
    pass
116

117

118
# Configuration providers
119
cdef class ConfigurationOption(Provider):
120
    cdef tuple _name
121
    cdef Configuration _root
122
    cdef dict _children
123
    cdef bint _required
124
    cdef object _cache
125

126

127
cdef class TypedConfigurationOption(Callable):
128
    pass
129

130

131
cdef class Configuration(Object):
132
    cdef str _name
133
    cdef bint __strict
134
    cdef dict _children
135
    cdef list _ini_files
136
    cdef list _yaml_files
137
    cdef list _json_files
138
    cdef list _pydantic_settings
139
    cdef object __weakref__
140

141

142
# Factory providers
143
cdef class Factory(Provider):
144
    cdef Callable _instantiator
145

146
    cdef tuple _attributes
147
    cdef int _attributes_len
148

149
    cpdef object _provide(self, tuple args, dict kwargs)
150

151

152
cdef class DelegatedFactory(Factory):
153
    pass
154

155

156
cdef class AbstractFactory(Factory):
157
    cpdef object _provide(self, tuple args, dict kwargs)
158

159

160
cdef class FactoryDelegate(Delegate):
161
    pass
162

163

164
cdef class FactoryAggregate(Aggregate):
165
    pass
166

167

168
# Singleton providers
169
cdef class BaseSingleton(Provider):
170
    cdef Factory _instantiator
171
    cdef object _storage
172

173

174
cdef class Singleton(BaseSingleton):
175

176
    cpdef object _provide(self, tuple args, dict kwargs)
177

178

179
cdef class DelegatedSingleton(Singleton):
180
    pass
181

182

183
cdef class ThreadSafeSingleton(BaseSingleton):
184
    cdef object _storage_lock
185

186
    cpdef object _provide(self, tuple args, dict kwargs)
187

188

189
cdef class DelegatedThreadSafeSingleton(ThreadSafeSingleton):
190
    pass
191

192

193
cdef class ThreadLocalSingleton(BaseSingleton):
194

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

197

198
cdef class ContextLocalSingleton(BaseSingleton):
199

200
    cpdef object _provide(self, tuple args, dict kwargs)
201

202

203
cdef class DelegatedThreadLocalSingleton(ThreadLocalSingleton):
204
    pass
205

206

207
cdef class AbstractSingleton(BaseSingleton):
208
    pass
209

210

211
cdef class SingletonDelegate(Delegate):
212
    pass
213

214

215
# Miscellaneous providers
216

217
cdef class List(Provider):
218
    cdef tuple _args
219
    cdef int _args_len
220

221
    cpdef object _provide(self, tuple args, dict kwargs)
222

223

224
cdef class Dict(Provider):
225
    cdef tuple _kwargs
226
    cdef int _kwargs_len
227

228
    cpdef object _provide(self, tuple args, dict kwargs)
229

230

231
cdef class Resource(Provider):
232
    cdef object _provides
233
    cdef bint _initialized
234
    cdef object _shutdowner
235
    cdef object _resource
236

237
    cdef tuple _args
238
    cdef int _args_len
239

240
    cdef tuple _kwargs
241
    cdef int _kwargs_len
242

243
    cpdef object _provide(self, tuple args, dict kwargs)
244

245

246
cdef class Container(Provider):
247
    cdef object _container_cls
248
    cdef dict _overriding_providers
249
    cdef object _container
250
    cdef object _parent
251

252
    cpdef object _provide(self, tuple args, dict kwargs)
253

254

255
cdef class Selector(Provider):
256
    cdef object _selector
257
    cdef dict _providers
258

259
    cpdef object _provide(self, tuple args, dict kwargs)
260

261
# Provided instance
262

263
cdef class ProvidedInstance(Provider):
264
    cdef object _provides
265

266
    cpdef object _provide(self, tuple args, dict kwargs)
267

268

269
cdef class AttributeGetter(Provider):
270
    cdef object _provides
271
    cdef object _name
272

273
    cpdef object _provide(self, tuple args, dict kwargs)
274

275

276
cdef class ItemGetter(Provider):
277
    cdef object _provides
278
    cdef object _name
279

280
    cpdef object _provide(self, tuple args, dict kwargs)
281

282

283
cdef class MethodCaller(Provider):
284
    cdef object _provides
285
    cdef tuple _args
286
    cdef int _args_len
287
    cdef tuple _kwargs
288
    cdef int _kwargs_len
289

290
    cpdef object _provide(self, tuple args, dict kwargs)
291

292

293
# Injections
294
cdef class Injection(object):
295
    cdef object _value
296
    cdef int _is_provider
297
    cdef int _is_delegated
298
    cdef int _call
299

300

301
cdef class PositionalInjection(Injection):
302
    pass
303

304

305
cdef class NamedInjection(Injection):
306
    cdef object _name
307

308

309
cpdef tuple parse_positional_injections(tuple args)
310

311

312
cpdef tuple parse_named_injections(dict kwargs)
313

314

315
# Utils
316
cdef class OverridingContext(object):
317
    cdef Provider _overridden
318
    cdef Provider _overriding
319

320

321
cdef class BaseSingletonResetContext(object):
322
    cdef object _singleton
323

324

325
cdef class SingletonResetContext(BaseSingletonResetContext):
326
    pass
327

328

329
cdef class SingletonFullResetContext(BaseSingletonResetContext):
330
    pass
331

332

333
cdef object CLASS_TYPES
334

335

336
cpdef bint is_provider(object instance)
337

338

339
cpdef object ensure_is_provider(object instance)
340

341

342
cpdef bint is_delegated(object instance)
343

344

345
cpdef str represent_provider(object provider, object provides)
346

347

348
cpdef bint is_container_instance(object instance)
349

350

351
cpdef bint is_container_class(object instance)
352

353

354
cpdef object deepcopy(object instance, dict memo=*)
355

356

357
# Inline helper functions
358
cdef inline object __get_name(NamedInjection self):
×
359
    return self._name
1✔
360

361

362
cdef inline object __get_value(Injection self):
×
363
    if self._call == 0:
1✔
364
        return self._value
1✔
365
    return self._value()
1✔
366

367

368
cdef inline object __get_value_kwargs(Injection self, dict kwargs):
×
369
    if self._call == 0:
1✔
370
        return self._value
×
371
    return self._value(**kwargs)
1✔
372

373

374
cdef inline tuple __separate_prefixed_kwargs(dict kwargs):
×
375
    cdef dict plain_kwargs = {}
1✔
376
    cdef dict prefixed_kwargs = {}
1✔
377

378
    for key, value in kwargs.items():
1✔
379
        if "__" not in key:
1✔
380
            plain_kwargs[key] = value
1✔
381
            continue
1✔
382

383
        index = key.index("__")
1✔
384
        prefix, name = key[:index], key[index+2:]
1✔
385

386
        if prefix not in prefixed_kwargs:
1✔
387
            prefixed_kwargs[prefix] = {}
1✔
388
        prefixed_kwargs[prefix][name] = value
1✔
389

390
    return plain_kwargs, prefixed_kwargs
1✔
391

392

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

407
    if inj_args_len == 0:
1✔
408
        return args
1✔
409

410
    for index in range(inj_args_len):
1✔
411
        injection = <PositionalInjection>inj_args[index]
1✔
412
        value = __get_value(injection)
1✔
413
        positional_args.append(value)
1✔
414

415
        if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
1✔
416
            future_args.append((index, value))
1✔
417

418
    positional_args.extend(args)
1✔
419

420
    if future_args:
1✔
421
        return __combine_future_injections(positional_args, future_args)
1✔
422

423
    return positional_args
1✔
424

425

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

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

452

453
        for index in range(inj_kwargs_len):
1✔
454
            kw_injection = <NamedInjection>inj_kwargs[index]
1✔
455
            name = __get_name(kw_injection)
1✔
456

457
            if name in kwargs:
1✔
458
                continue
1✔
459

460
            if name in prefixed:
1✔
461
                value = __get_value_kwargs(kw_injection, prefixed[name])
1✔
462
            else:
463
                value = __get_value(kw_injection)
1✔
464

465
            kwargs[name] = value
1✔
466
            if async_mode != ASYNC_MODE_DISABLED and __is_future_or_coroutine(value):
1✔
467
                future_kwargs.append((name, value))
1✔
468

469
    if future_kwargs:
1✔
470
        return __combine_future_injections(kwargs, future_kwargs)
1✔
471

472
    return kwargs
1✔
473

474

475
cdef inline object __combine_future_injections(object injections, list future_injections):
×
476
    future_result = asyncio.Future()
1✔
477

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

489
    return future_result
1✔
490

491

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

507

508
@cython.boundscheck(False)
509
@cython.wraparound(False)
510
cdef inline object __provide_attributes(tuple attributes, int attributes_len):
×
511
    cdef NamedInjection attr_injection
512
    cdef dict attribute_injections = {}
1✔
513
    cdef list future_attributes = []
1✔
514

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

523
    if future_attributes:
1✔
524
        return __combine_future_injections(attribute_injections, future_attributes)
1✔
525

526
    return attribute_injections
1✔
527

528

529
cdef inline object __async_inject_attributes(future_instance, future_attributes):
×
530
    future_result = asyncio.Future()
1✔
531

532
    attributes_ready = asyncio.gather(future_instance, future_attributes)
1✔
533
    attributes_ready.add_done_callback(
1✔
534
        functools.partial(
1✔
535
            __async_inject_attributes_callback,
1✔
536
            future_result,
1✔
537
        ),
538
    )
539
    asyncio.ensure_future(attributes_ready)
1✔
540

541
    return future_result
1✔
542

543

544
cdef inline void __async_inject_attributes_callback(object future_result, object future):
×
545
    try:
1✔
546
        instance, attributes = future.result()
1✔
547

548
        for name, value in attributes.items():
1✔
549
            setattr(instance, name, value)
1✔
550
    except Exception as exception:
1✔
551
        future_result.set_exception(exception)
1✔
552
    else:
553
        future_result.set_result(instance)
1✔
554

555

556
cdef inline void __inject_attributes(object instance, dict attributes):
×
557
    for name, value in attributes.items():
1✔
558
        setattr(instance, name, value)
1✔
559

560

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

584
    if async_mode == ASYNC_MODE_DISABLED:
1✔
585
        return call(*args, **kwargs)
1✔
586

587
    cdef bint is_future_args = __is_future_or_coroutine(args)
1✔
588
    cdef bint is_future_kwargs = __is_future_or_coroutine(kwargs)
1✔
589

590
    if is_future_args or is_future_kwargs:
1✔
591
        future_args = args if is_future_args else __future_result(args)
1✔
592
        future_kwargs = kwargs if is_future_kwargs else __future_result(kwargs)
1✔
593

594
        future_result = asyncio.Future()
1✔
595

596
        args_kwargs_ready = asyncio.gather(future_args, future_kwargs)
1✔
597
        args_kwargs_ready.add_done_callback(
1✔
598
            functools.partial(
1✔
599
                __async_call_callback,
1✔
600
                future_result,
601
                call,
1✔
602
            ),
603
        )
604
        asyncio.ensure_future(args_kwargs_ready)
1✔
605

606
        return future_result
1✔
607

608
    return call(*args, **kwargs)
1✔
609

610

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

624

625
cdef inline object __async_result_callback(object future_result, object future):
×
626
    try:
1✔
627
        result = future.result()
1✔
628
    except Exception as exception:
1✔
629
        future_result.set_exception(exception)
1✔
630
    else:
631
        future_result.set_result(result)
1✔
632

633

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

646

647
cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
×
648
    cdef object instance
649

650
    instance = __call(
1✔
651
        self._instantiator._provides,
1✔
652
        args,
653
        self._instantiator._args,
1✔
654
        self._instantiator._args_len,
655
        kwargs,
656
        self._instantiator._kwargs,
1✔
657
        self._instantiator._kwargs_len,
658
        self._async_mode,
659
    )
660

661
    if self._attributes_len > 0:
1✔
662
        attributes = __provide_attributes(self._attributes, self._attributes_len)
1✔
663

664
        is_future_instance = __is_future_or_coroutine(instance)
1✔
665
        is_future_attributes = __is_future_or_coroutine(attributes)
1✔
666

667
        if is_future_instance or is_future_attributes:
1✔
668
            future_instance = instance if is_future_instance else __future_result(instance)
1✔
669
            future_attributes = attributes if is_future_attributes else __future_result(attributes)
1✔
670
            return __async_inject_attributes(future_instance, future_attributes)
1✔
671

672
        __inject_attributes(instance, attributes)
1✔
673

674
    return instance
1✔
675

676

677
cdef inline bint __is_future_or_coroutine(object instance):
×
678
    return __isfuture(instance) or __iscoroutine(instance)
1✔
679

680

681
cdef inline bint __isfuture(object obj):
×
682
    return hasattr(obj.__class__, "_asyncio_future_blocking") and obj._asyncio_future_blocking is not None
1✔
683

684

685
cdef inline bint __iscoroutine(object obj):
×
686
    if type(obj) in __iscoroutine_typecache:
1✔
687
        return True
1✔
688

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

699

700
cdef inline object __future_result(object instance):
×
701
    future_result = asyncio.Future()
1✔
702
    future_result.set_result(instance)
1✔
703
    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