Skip to content

Commit 8fcfde8

Browse files
committed
refactor(tests): replace type:ignore comments with proper type annotations
Builds on PR #782 to replace the `# type: ignore` suppressions with real type annotations and structural fixes: - Use `isinstance(value, OnError|OnNext)` to narrow `Recorded.value` instead of `# type: ignore[union-attr]` (test_average, test_elementat, test_reduce, test_toiterable). - Properly annotate test-local `subscribe` functions with `ObserverBase[T] / SchedulerBase | None / DisposableBase` and return `Disposable()` so `reactivex.create(...)` accepts them without `# type: ignore[misc]/[arg-type]` (test_concat, test_observeon, test_map, test_skipuntil, test_while_do). - Type `xs` as `list[ColdObservable[int] | None]` in test_defer instead of bare `[None]`, and add `assert xs[0] is not None` narrowing. - Annotate `_raise` as `NoReturn` in test_map, test_retry, test_generate so the surrounding code type-checks without trailing dummy returns. - Use a typed module-level seed in test_generate to widen `Literal[0]` to `int` so `lambda x: x + 1` matches `Mapper[int, int]`. - `cast(Observable[int], s)` in test_tofuture instead of `# type: ignore`. Also widens two clearly-incorrect public type signatures (the implementation already supports the wider input): - `delay()` and `delay_()` now accept `AbsoluteOrRelativeTime` instead of only `RelativeTime`. The implementation already branches on `isinstance(duetime, datetime)`, so this just makes the signature match reality and removes 5 `# type: ignore[arg-type]` in test_delay. - `from_callback()` now returns `Callable[..., Observable[Any]]` instead of `Callable[[], Observable[Any]]`. The inner `function(*args)` already accepts arbitrary args, so this matches reality and removes 2 `# type: ignore[call-arg]` in test_fromcallback. Only `test_of.py:51` keeps a `# type: ignore[call-arg]` — it's in a test that never runs (typo `teest_` in the name) and intentionally calls `reactivex.of()` with a kwarg that doesn't exist; fixing it is out of scope. Pyright strict: 0 errors. All 1494 tests pass.
1 parent 2516580 commit 8fcfde8

23 files changed

Lines changed: 143 additions & 66 deletions

reactivex/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ def from_callable(
469469
def from_callback(
470470
func: Callable[..., Callable[..., None]],
471471
mapper: typing.Mapper[Any, Any] | None = None,
472-
) -> Callable[[], Observable[Any]]:
472+
) -> Callable[..., Observable[Any]]:
473473
"""Converts a callback function to an observable sequence.
474474
475475
Args:

reactivex/observable/fromcallback.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
def from_callback_(
99
func: Callable[..., Callable[..., None]],
1010
mapper: typing.Mapper[Any, Any] | None = None,
11-
) -> Callable[[], Observable[Any]]:
11+
) -> Callable[..., Observable[Any]]:
1212
"""Converts a callback function to an observable sequence.
1313
1414
Args:

reactivex/operators/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,8 @@ def dematerialize() -> Callable[[Observable[Notification[_T]]], Observable[_T]]:
707707

708708

709709
def delay(
710-
duetime: typing.RelativeTime, scheduler: abc.SchedulerBase | None = None
710+
duetime: typing.AbsoluteOrRelativeTime,
711+
scheduler: abc.SchedulerBase | None = None,
711712
) -> Callable[[Observable[_T]], Observable[_T]]:
712713
"""The delay operator.
713714

reactivex/operators/_delay.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
def observable_delay_timespan(
2222
source: Observable[_T],
23-
duetime: typing.RelativeTime,
23+
duetime: typing.AbsoluteOrRelativeTime,
2424
scheduler: abc.SchedulerBase | None = None,
2525
) -> Observable[_T]:
2626
def subscribe(
@@ -119,7 +119,7 @@ def action(scheduler: abc.SchedulerBase, state: Any = None):
119119
@curry_flip
120120
def delay_(
121121
source: Observable[_T],
122-
duetime: typing.RelativeTime,
122+
duetime: typing.AbsoluteOrRelativeTime,
123123
scheduler: abc.SchedulerBase | None = None,
124124
) -> Observable[_T]:
125125
"""Time shifts the observable sequence.

tests/test_observable/test_average.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22

33
from reactivex import operators as _
4+
from reactivex.notification import OnError
45
from reactivex.testing import ReactiveTest, TestScheduler
56

67
on_next = ReactiveTest.on_next
@@ -20,7 +21,7 @@ def test_average_int32_empty(self):
2021
res = scheduler.start(create=lambda: xs.pipe(_.average())).messages
2122

2223
assert len(res) == 1
23-
assert res[0].value.kind == "E" and res[0].value.exception is not None # type: ignore[union-attr]
24+
assert isinstance(res[0].value, OnError) and res[0].value.exception is not None
2425
assert res[0].time == 250
2526

2627
def test_average_int32_return(self):

tests/test_observable/test_concat.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import unittest
22

33
import reactivex
4+
from reactivex import abc
45
from reactivex import operators as ops
6+
from reactivex.disposable import Disposable
57
from reactivex.testing import ReactiveTest, TestScheduler
68

79
on_next = ReactiveTest.on_next
@@ -227,16 +229,24 @@ def test_concat_forward_scheduler(self):
227229
scheduler = TestScheduler()
228230
subscribe_schedulers: dict[str, object] = {"e1": "unknown", "e2": "unknown"}
229231

230-
def subscribe_e1(observer, scheduler=None): # type: ignore[misc]
232+
def subscribe_e1(
233+
observer: abc.ObserverBase[int],
234+
scheduler: abc.SchedulerBase | None = None,
235+
) -> abc.DisposableBase:
231236
subscribe_schedulers["e1"] = scheduler
232237
observer.on_completed()
238+
return Disposable()
233239

234-
def subscribe_e2(observer, scheduler=None): # type: ignore[misc]
240+
def subscribe_e2(
241+
observer: abc.ObserverBase[int],
242+
scheduler: abc.SchedulerBase | None = None,
243+
) -> abc.DisposableBase:
235244
subscribe_schedulers["e2"] = scheduler
236245
observer.on_completed()
246+
return Disposable()
237247

238-
e1 = reactivex.create(subscribe_e1) # type: ignore[arg-type]
239-
e2 = reactivex.create(subscribe_e2) # type: ignore[arg-type]
248+
e1 = reactivex.create(subscribe_e1)
249+
e2 = reactivex.create(subscribe_e2)
240250

241251
stream = e1.pipe(ops.concat(e2))
242252
stream.subscribe(scheduler=scheduler)
@@ -247,16 +257,24 @@ def subscribe_e2(observer, scheduler=None): # type: ignore[misc]
247257
def test_concat_forward_none_scheduler(self):
248258
subscribe_schedulers: dict[str, object] = {"e1": "unknown", "e2": "unknown"}
249259

250-
def subscribe_e1(observer, scheduler=None): # type: ignore[misc]
260+
def subscribe_e1(
261+
observer: abc.ObserverBase[int],
262+
scheduler: abc.SchedulerBase | None = None,
263+
) -> abc.DisposableBase:
251264
subscribe_schedulers["e1"] = scheduler
252265
observer.on_completed()
266+
return Disposable()
253267

254-
def subscribe_e2(observer, scheduler=None): # type: ignore[misc]
268+
def subscribe_e2(
269+
observer: abc.ObserverBase[int],
270+
scheduler: abc.SchedulerBase | None = None,
271+
) -> abc.DisposableBase:
255272
subscribe_schedulers["e2"] = scheduler
256273
observer.on_completed()
274+
return Disposable()
257275

258-
e1 = reactivex.create(subscribe_e1) # type: ignore[arg-type]
259-
e2 = reactivex.create(subscribe_e2) # type: ignore[arg-type]
276+
e1 = reactivex.create(subscribe_e1)
277+
e2 = reactivex.create(subscribe_e2)
260278

261279
stream = e1.pipe(ops.concat(e2))
262280
stream.subscribe()

tests/test_observable/test_defer.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import reactivex
44
from reactivex.testing import ReactiveTest, TestScheduler
5+
from reactivex.testing.coldobservable import ColdObservable
56

67
on_next = ReactiveTest.on_next
78
on_completed = ReactiveTest.on_completed
@@ -23,7 +24,7 @@ def _raise(ex):
2324

2425
class TestDefer(unittest.TestCase):
2526
def test_defer_complete(self):
26-
xs = [None]
27+
xs: list[ColdObservable[int] | None] = [None]
2728
invoked = [0]
2829
scheduler = TestScheduler()
2930

@@ -40,12 +41,13 @@ def defer(scheduler):
4041
results = scheduler.start(create)
4142
assert results.messages == [on_next(300, 200), on_completed(400)]
4243
assert 1 == invoked[0]
43-
assert xs[0].subscriptions == [subscribe(200, 400)] # type: ignore[union-attr]
44+
assert xs[0] is not None
45+
assert xs[0].subscriptions == [subscribe(200, 400)]
4446

4547
def test_defer_error(self):
4648
scheduler = TestScheduler()
4749
invoked = [0]
48-
xs = [None]
50+
xs: list[ColdObservable[int] | None] = [None]
4951
ex = "ex"
5052

5153
def create():
@@ -62,12 +64,13 @@ def defer(scheduler):
6264

6365
assert results.messages == [on_next(300, 200), on_error(400, ex)]
6466
assert 1 == invoked[0]
65-
assert xs[0].subscriptions == [subscribe(200, 400)] # type: ignore[union-attr]
67+
assert xs[0] is not None
68+
assert xs[0].subscriptions == [subscribe(200, 400)]
6669

6770
def test_defer_dispose(self):
6871
scheduler = TestScheduler()
6972
invoked = [0]
70-
xs = [None]
73+
xs: list[ColdObservable[int] | None] = [None]
7174

7275
def create():
7376
def defer(scheduler):
@@ -84,7 +87,8 @@ def defer(scheduler):
8487
results = scheduler.start(create)
8588
assert results.messages == [on_next(300, 200), on_next(400, 1)]
8689
assert 1 == invoked[0]
87-
assert xs[0].subscriptions == [subscribe(200, 1000)] # type: ignore[union-attr]
90+
assert xs[0] is not None
91+
assert xs[0].subscriptions == [subscribe(200, 1000)]
8892

8993
def test_defer_on_error(self):
9094
scheduler = TestScheduler()

tests/test_observable/test_delay.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def test_delay_datetime_offset_simple1_impl(self):
6363

6464
def create():
6565
dt = datetime.fromtimestamp(300.0, tz=timezone.utc)
66-
return xs.pipe(delay(dt)) # type: ignore[arg-type]
66+
return xs.pipe(delay(dt))
6767

6868
results = scheduler.start(create)
6969
assert results.messages == [
@@ -107,7 +107,7 @@ def test_delay_datetime_offset_simple2_impl(self):
107107
)
108108

109109
def create():
110-
return xs.pipe(delay(datetime.fromtimestamp(250, tz=timezone.utc))) # type: ignore[arg-type]
110+
return xs.pipe(delay(datetime.fromtimestamp(250, tz=timezone.utc)))
111111

112112
results = scheduler.start(create)
113113

@@ -153,7 +153,7 @@ def test_delay_datetime_offset_simple3_impl(self):
153153
)
154154

155155
def create():
156-
return xs.pipe(delay(datetime.fromtimestamp(350, tz=timezone.utc))) # type: ignore[arg-type]
156+
return xs.pipe(delay(datetime.fromtimestamp(350, tz=timezone.utc)))
157157

158158
results = scheduler.start(create)
159159

@@ -201,7 +201,7 @@ def test_delay_datetime_offset_error1_impl(self):
201201
)
202202

203203
def create():
204-
return xs.pipe(delay(datetime.fromtimestamp(250, tz=timezone.utc))) # type: ignore[arg-type]
204+
return xs.pipe(delay(datetime.fromtimestamp(250, tz=timezone.utc)))
205205

206206
results = scheduler.start(create)
207207

@@ -244,7 +244,7 @@ def test_delay_datetime_offset_error2_impl(self):
244244
)
245245

246246
def create():
247-
return xs.pipe(delay(datetime.fromtimestamp(350, tz=timezone.utc))) # type: ignore[arg-type]
247+
return xs.pipe(delay(datetime.fromtimestamp(350, tz=timezone.utc)))
248248

249249
results = scheduler.start(create)
250250

tests/test_observable/test_elementat.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22

33
from reactivex import operators as ops
4+
from reactivex.notification import OnError
45
from reactivex.testing import ReactiveTest, TestScheduler
56

67
on_next = ReactiveTest.on_next
@@ -54,8 +55,9 @@ def create():
5455

5556
self.assertEqual(1, len(results.messages))
5657
self.assertEqual(600, results.messages[0].time)
57-
self.assertEqual("E", results.messages[0].value.kind) # type: ignore[union-attr]
58-
assert results.messages[0].value.exception # type: ignore[union-attr]
58+
value = results.messages[0].value
59+
assert isinstance(value, OnError)
60+
assert value.exception
5961

6062
def test_elementat_error(self):
6163
ex = "ex"

tests/test_observable/test_empty.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ def test_empty_observer_throw_exception(self):
4545
scheduler = TestScheduler()
4646
xs = empty()
4747
xs.subscribe(
48-
lambda x: None, lambda ex: None, lambda: _raise(Exception("ex")), scheduler=scheduler
48+
lambda x: None,
49+
lambda ex: None,
50+
lambda: _raise(Exception("ex")),
51+
scheduler=scheduler,
4952
)
5053

5154
with self.assertRaises(RxException):

0 commit comments

Comments
 (0)