1111
1212from ddtrace import ext
1313from ddtrace .internal .datadog .profiling import ddup
14+ from ddtrace .profiling .collector .asyncio import AsyncioBoundedSemaphoreCollector
1415from ddtrace .profiling .collector .asyncio import AsyncioLockCollector
1516from ddtrace .profiling .collector .asyncio import AsyncioSemaphoreCollector
1617from tests .profiling .collector import pprof_utils
2324
2425PY_311_OR_ABOVE = sys .version_info [:2 ] >= (3 , 11 )
2526
26- # Type aliases for collector and lock types
27- CollectorType = Union [
27+ # Type aliases for supported classes
28+ LockTypeClass = Union [Type [asyncio .Lock ], Type [asyncio .Semaphore ], Type [asyncio .BoundedSemaphore ]]
29+ LockTypeInst = Union [asyncio .Lock , asyncio .Semaphore , asyncio .BoundedSemaphore ]
30+
31+ CollectorTypeClass = Union [
2832 Type [AsyncioLockCollector ],
2933 Type [AsyncioSemaphoreCollector ],
34+ Type [AsyncioBoundedSemaphoreCollector ],
3035]
31- LockType = Union [Type [ asyncio . Lock ], Type [ asyncio . Semaphore ] ]
36+ CollectorTypeInst = Union [AsyncioLockCollector , AsyncioSemaphoreCollector , AsyncioBoundedSemaphoreCollector ]
3237
3338
3439@pytest .mark .parametrize (
4247 AsyncioSemaphoreCollector ,
4348 "AsyncioSemaphoreCollector(status=<ServiceStatus.STOPPED: 'stopped'>, capture_pct=1.0, nframes=64, tracer=None)" , # noqa: E501
4449 ),
50+ (
51+ AsyncioBoundedSemaphoreCollector ,
52+ "AsyncioBoundedSemaphoreCollector(status=<ServiceStatus.STOPPED: 'stopped'>, capture_pct=1.0, nframes=64, tracer=None)" ,
53+ ),
4554 ],
4655)
47- def test_collector_repr (collector_class : CollectorType , expected_repr : str ) -> None :
56+ def test_collector_repr (collector_class : CollectorTypeClass , expected_repr : str ) -> None :
4857 test_collector ._test_repr (collector_class , expected_repr )
4958
5059
@@ -59,11 +68,11 @@ class BaseAsyncioLockCollectorTest:
5968 """
6069
6170 @property
62- def collector_class (self ) -> CollectorType :
71+ def collector_class (self ) -> CollectorTypeClass :
6372 raise NotImplementedError ("Child classes must implement collector_class" )
6473
6574 @property
66- def lock_class (self ) -> LockType :
75+ def lock_class (self ) -> LockTypeClass :
6776 raise NotImplementedError ("Child classes must implement lock_class" )
6877
6978 def setup_method (self , method ):
@@ -229,3 +238,40 @@ def collector_class(self):
229238 @property
230239 def lock_class (self ):
231240 return asyncio .Semaphore
241+ < << << << HEAD
242+ == == == =
243+
244+ @property
245+ def lock_init_args (self ):
246+ return (2 ,) # Initial semaphore value
247+
248+
249+ class TestAsyncioBoundedSemaphoreCollector (BaseAsyncioLockCollectorTest ):
250+ """Test asyncio.BoundedSemaphore profiling."""
251+
252+ @property
253+ def collector_class (self ):
254+ return AsyncioBoundedSemaphoreCollector
255+
256+ @property
257+ def lock_class (self ):
258+ return asyncio .BoundedSemaphore
259+
260+ @property
261+ def lock_init_args (self ):
262+ return (2 ,) # Initial semaphore value
263+
264+ async def test_bounded_behavior_preserved (self ):
265+ """Test that profiling wrapper preserves BoundedSemaphore's bounded behavior.
266+
267+ This verifies the wrapper doesn't interfere with BoundedSemaphore's unique characteristic:
268+ raising ValueError when releasing beyond the initial value.
269+ """
270+ with self .collector_class (capture_pct = 100 ):
271+ bs = asyncio .BoundedSemaphore (1 )
272+ await bs .acquire ()
273+ bs .release ()
274+ # BoundedSemaphore should raise ValueError when releasing more than initial value
275+ with pytest .raises (ValueError , match = "BoundedSemaphore released too many times" ):
276+ bs .release ()
277+ >> >> >> > 8 b01f85068 (feat (profiling ): profile asyncio .BoundedSemaphore primitives with Python Lock profiler )
0 commit comments