Skip to content

Commit 727f94b

Browse files
committed
[common] Simplify FrameTimecode implementation
1 parent de5a63b commit 727f94b

File tree

2 files changed

+41
-133
lines changed

2 files changed

+41
-133
lines changed

scenedetect/common.py

Lines changed: 37 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -402,21 +402,44 @@ def _parse_timecode_string(self, input: str) -> int:
402402
raise ValueError("Timecode seconds value must be positive.")
403403
return self._seconds_to_frames(as_float)
404404

405-
def __iadd__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTimecode":
405+
def _get_other_as_frames(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> int:
406+
"""Get the frame number from `other` for arithmetic operations."""
406407
if isinstance(other, int):
407-
self._frame_num += other
408-
elif isinstance(other, FrameTimecode):
408+
return other
409+
if isinstance(other, float):
410+
return self._seconds_to_frames(other)
411+
if isinstance(other, str):
412+
return self._parse_timecode_string(other)
413+
if isinstance(other, FrameTimecode):
409414
if self.equal_framerate(other._framerate):
410-
self._frame_num += other._frame_num
411-
else:
412-
raise ValueError("FrameTimecode instances require equal framerate for addition.")
413-
# Check if value to add is in number of seconds.
414-
elif isinstance(other, float):
415-
self._frame_num += self._seconds_to_frames(other)
416-
elif isinstance(other, str):
417-
self._frame_num += self._parse_timecode_string(other)
418-
else:
419-
raise TypeError("Unsupported type for performing addition with FrameTimecode.")
415+
return other._frame_num
416+
raise ValueError("FrameTimecode instances require equal framerate for arithmetic.")
417+
raise TypeError("Unsupported type for performing arithmetic with FrameTimecode.")
418+
419+
def __eq__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
420+
if other is None:
421+
return False
422+
# Allow comparison with other types by converting them to frames.
423+
# If the framerate is not equal, a TypeError will be raised.
424+
return self.frame_num == self._get_other_as_frames(other)
425+
426+
def __ne__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
427+
return not self == other
428+
429+
def __lt__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
430+
return self.frame_num < self._get_other_as_frames(other)
431+
432+
def __le__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
433+
return self.frame_num <= self._get_other_as_frames(other)
434+
435+
def __gt__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
436+
return self.frame_num > self._get_other_as_frames(other)
437+
438+
def __ge__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
439+
return self.frame_num >= self._get_other_as_frames(other)
440+
441+
def __iadd__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTimecode":
442+
self._frame_num += self._get_other_as_frames(other)
420443
if self._frame_num < 0: # Required to allow adding negative seconds/frames.
421444
self._frame_num = 0
422445
return self
@@ -427,22 +450,7 @@ def __add__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTi
427450
return to_return
428451

429452
def __isub__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTimecode":
430-
if isinstance(other, int):
431-
self._frame_num -= other
432-
elif isinstance(other, FrameTimecode):
433-
if self.equal_framerate(other._framerate):
434-
self._frame_num -= other._frame_num
435-
else:
436-
raise ValueError("FrameTimecode instances require equal framerate for subtraction.")
437-
# Check if value to add is in number of seconds.
438-
elif isinstance(other, float):
439-
self._frame_num -= self._seconds_to_frames(other)
440-
elif isinstance(other, str):
441-
self._frame_num -= self._parse_timecode_string(other)
442-
else:
443-
raise TypeError(
444-
"Unsupported type for performing subtraction with FrameTimecode: %s" % type(other)
445-
)
453+
self._frame_num -= self._get_other_as_frames(other)
446454
if self._frame_num < 0:
447455
self._frame_num = 0
448456
return self
@@ -452,106 +460,6 @@ def __sub__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTi
452460
to_return -= other
453461
return to_return
454462

455-
def __eq__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> "FrameTimecode":
456-
if isinstance(other, int):
457-
return self._frame_num == other
458-
elif isinstance(other, float):
459-
return self.seconds == other
460-
elif isinstance(other, str):
461-
return self._frame_num == self._parse_timecode_string(other)
462-
elif isinstance(other, FrameTimecode):
463-
if self.equal_framerate(other._framerate):
464-
return self._frame_num == other._frame_num
465-
else:
466-
raise TypeError(
467-
"FrameTimecode objects must have the same framerate to be compared."
468-
)
469-
elif other is None:
470-
return False
471-
else:
472-
raise TypeError(
473-
"Unsupported type for performing == with FrameTimecode: %s" % type(other)
474-
)
475-
476-
def __ne__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
477-
return not self == other
478-
479-
def __lt__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
480-
if isinstance(other, int):
481-
return self._frame_num < other
482-
elif isinstance(other, float):
483-
return self.seconds < other
484-
elif isinstance(other, str):
485-
return self._frame_num < self._parse_timecode_string(other)
486-
elif isinstance(other, FrameTimecode):
487-
if self.equal_framerate(other._framerate):
488-
return self._frame_num < other._frame_num
489-
else:
490-
raise TypeError(
491-
"FrameTimecode objects must have the same framerate to be compared."
492-
)
493-
else:
494-
raise TypeError(
495-
"Unsupported type for performing < with FrameTimecode: %s" % type(other)
496-
)
497-
498-
def __le__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
499-
if isinstance(other, int):
500-
return self._frame_num <= other
501-
elif isinstance(other, float):
502-
return self.seconds <= other
503-
elif isinstance(other, str):
504-
return self._frame_num <= self._parse_timecode_string(other)
505-
elif isinstance(other, FrameTimecode):
506-
if self.equal_framerate(other._framerate):
507-
return self._frame_num <= other._frame_num
508-
else:
509-
raise TypeError(
510-
"FrameTimecode objects must have the same framerate to be compared."
511-
)
512-
else:
513-
raise TypeError(
514-
"Unsupported type for performing <= with FrameTimecode: %s" % type(other)
515-
)
516-
517-
def __gt__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
518-
if isinstance(other, int):
519-
return self._frame_num > other
520-
elif isinstance(other, float):
521-
return self.seconds > other
522-
elif isinstance(other, str):
523-
return self._frame_num > self._parse_timecode_string(other)
524-
elif isinstance(other, FrameTimecode):
525-
if self.equal_framerate(other._framerate):
526-
return self._frame_num > other._frame_num
527-
else:
528-
raise TypeError(
529-
"FrameTimecode objects must have the same framerate to be compared."
530-
)
531-
else:
532-
raise TypeError(
533-
"Unsupported type for performing > with FrameTimecode: %s" % type(other)
534-
)
535-
536-
def __ge__(self, other: ty.Union[int, float, str, "FrameTimecode"]) -> bool:
537-
if isinstance(other, int):
538-
return self._frame_num >= other
539-
elif isinstance(other, float):
540-
return self.seconds >= other
541-
elif isinstance(other, str):
542-
return self._frame_num >= self._parse_timecode_string(other)
543-
elif isinstance(other, FrameTimecode):
544-
if self.equal_framerate(other._framerate):
545-
return self._frame_num >= other._frame_num
546-
else:
547-
raise TypeError(
548-
"FrameTimecode objects must have the same framerate to be compared."
549-
)
550-
else:
551-
raise TypeError(
552-
"Unsupported type for performing >= with FrameTimecode: %s" % type(other)
553-
)
554-
555463
# TODO(v1.0): __int__ and __float__ should be removed. Mark as deprecated, and indicate
556464
# need to use relevant property instead.
557465

tests/test_frame_timecode.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ def test_equality():
200200
assert x != FrameTimecode(timecode=10.0, fps=10.0)
201201
assert x != FrameTimecode(timecode=10.0, fps=10.0)
202202
# Comparing FrameTimecodes with different framerates raises a TypeError.
203-
with pytest.raises(TypeError):
203+
with pytest.raises(ValueError):
204204
assert x == FrameTimecode(timecode=1.0, fps=100.0)
205-
with pytest.raises(TypeError):
205+
with pytest.raises(ValueError):
206206
assert x == FrameTimecode(timecode=1.0, fps=10.1)
207207

208208
assert x == FrameTimecode(x)
@@ -249,7 +249,7 @@ def test_addition():
249249

250250
assert x + 10 == "00:00:02.000"
251251

252-
with pytest.raises(TypeError):
252+
with pytest.raises(ValueError):
253253
assert FrameTimecode("00:00:02.000", fps=20.0) == x + 10
254254

255255

@@ -268,7 +268,7 @@ def test_subtraction():
268268

269269
assert x - 1 == FrameTimecode(timecode=0.9, fps=10.0)
270270

271-
with pytest.raises(TypeError):
271+
with pytest.raises(ValueError):
272272
assert FrameTimecode("00:00:02.000", fps=20.0) == x - 10
273273

274274

0 commit comments

Comments
 (0)