Skip to content

Commit a3b8a25

Browse files
committed
Merge branch 'develop' into MR/newapi
2 parents d16f479 + c71ce61 commit a3b8a25

2 files changed

Lines changed: 54 additions & 47 deletions

File tree

src/timecode/timecode.py

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -552,13 +552,16 @@ def __eq__(self, other: int | str | Timecode | object) -> bool:
552552
bool: True if the other is equal to this Timecode instance.
553553
"""
554554
if isinstance(other, Timecode):
555-
return self.framerate == other.framerate and self.frames == other.frames
555+
if self.framerate != other.framerate:
556+
raise ValueError("'==' not supported between instances of "
557+
"'Timecode' with different framerates")
558+
return self.frames == other.frames
556559
if isinstance(other, str):
557560
new_tc = Timecode(self.framerate, other)
558561
return self.__eq__(new_tc)
559562
if isinstance(other, int):
560563
return self.frames == other
561-
return False
564+
return NotImplemented
562565

563566
def __ge__(self, other: int | str | Timecode | object) -> bool:
564567
"""Override greater than or equal to operator.
@@ -574,16 +577,16 @@ def __ge__(self, other: int | str | Timecode | object) -> bool:
574577
instance.
575578
"""
576579
if isinstance(other, Timecode):
577-
return self.framerate == other.framerate and self.frames >= other.frames
580+
if self.framerate != other.framerate:
581+
raise ValueError("'>=' not supported between instances of "
582+
"'Timecode' with different framerates")
583+
return self.frames >= other.frames
578584
if isinstance(other, str):
579585
new_tc = Timecode(self.framerate, other)
580586
return self.frames >= new_tc.frames
581587
if isinstance(other, int):
582588
return self.frames >= other
583-
raise TypeError(
584-
"'>=' not supported between instances of 'Timecode' and "
585-
f"'{other.__class__.__name__}'"
586-
)
589+
return NotImplemented
587590

588591
def __gt__(self, other: int | str | Timecode) -> bool:
589592
"""Override greater than operator.
@@ -598,16 +601,16 @@ def __gt__(self, other: int | str | Timecode) -> bool:
598601
bool: True if the other is greater than this Timecode instance.
599602
"""
600603
if isinstance(other, Timecode):
601-
return self.framerate == other.framerate and self.frames > other.frames
604+
if self.framerate != other.framerate:
605+
raise ValueError("'>' not supported between instances of "
606+
"'Timecode' with different framerates")
607+
return self.frames > other.frames
602608
if isinstance(other, str):
603609
new_tc = Timecode(self.framerate, other)
604610
return self.frames > new_tc.frames
605611
if isinstance(other, int):
606612
return self.frames > other
607-
raise TypeError(
608-
"'>' not supported between instances of 'Timecode' and "
609-
f"'{other.__class__.__name__}'"
610-
)
613+
return NotImplemented
611614

612615
def __le__(self, other: int | str | Timecode | object) -> bool:
613616
"""Override less or equal to operator.
@@ -622,16 +625,16 @@ def __le__(self, other: int | str | Timecode | object) -> bool:
622625
bool: True if the other is less than or equal to this Timecode instance.
623626
"""
624627
if isinstance(other, Timecode):
625-
return self.framerate == other.framerate and self.frames <= other.frames
628+
if self.framerate != other.framerate:
629+
raise ValueError("'<=' not supported between instances of "
630+
"'Timecode' with different framerates")
631+
return self.frames <= other.frames
626632
if isinstance(other, str):
627633
new_tc = Timecode(self.framerate, other)
628634
return self.frames <= new_tc.frames
629635
if isinstance(other, int):
630636
return self.frames <= other
631-
raise TypeError(
632-
"'<' not supported between instances of 'Timecode' and "
633-
f"'{other.__class__.__name__}'"
634-
)
637+
return NotImplemented
635638

636639
def __lt__(self, other: int | str | Timecode) -> bool:
637640
"""Override less than operator.
@@ -646,16 +649,16 @@ def __lt__(self, other: int | str | Timecode) -> bool:
646649
bool: True if the other is less than this Timecode instance.
647650
"""
648651
if isinstance(other, Timecode):
652+
if self.framerate != other.framerate:
653+
raise ValueError("'<' not supported between instances of "
654+
"'Timecode' with different framerates")
649655
return self.framerate == other.framerate and self.frames < other.frames
650656
if isinstance(other, str):
651657
new_tc = Timecode(self.framerate, other)
652658
return self.frames < new_tc.frames
653659
if isinstance(other, int):
654660
return self.frames < other
655-
raise TypeError(
656-
"'<=' not supported between instances of 'Timecode' and "
657-
f"'{other.__class__.__name__}'"
658-
)
661+
return NotImplemented
659662

660663
def __add__(self, other: int | Timecode) -> Timecode:
661664
"""Return a new Timecode with the given timecode or frames added to this one.
@@ -679,9 +682,7 @@ def __add__(self, other: int | Timecode) -> Timecode:
679682
elif isinstance(other, int):
680683
tc.add_frames(other)
681684
else:
682-
raise TimecodeError(
683-
f"Type {other.__class__.__name__} not supported for arithmetic."
684-
)
685+
return NotImplemented
685686

686687
return tc
687688

@@ -703,9 +704,7 @@ def __sub__(self, other: int | Timecode) -> Timecode:
703704
elif isinstance(other, int):
704705
subtracted_frames = self.frames - other
705706
else:
706-
raise TimecodeError(
707-
f"Type {other.__class__.__name__} not supported for arithmetic."
708-
)
707+
return NotImplemented
709708
tc = Timecode(self.framerate, frames=abs(subtracted_frames))
710709
tc._copy_props_from(self)
711710
return tc
@@ -728,9 +727,7 @@ def __mul__(self, other: int | Timecode) -> Timecode:
728727
elif isinstance(other, int):
729728
multiplied_frames = self.frames * other
730729
else:
731-
raise TimecodeError(
732-
f"Type {other.__class__.__name__} not supported for arithmetic."
733-
)
730+
return NotImplemented
734731
tc = Timecode(self.framerate, frames=multiplied_frames)
735732
tc._copy_props_from(self)
736733
return tc
@@ -753,9 +750,7 @@ def __div__(self, other: int | Timecode) -> Timecode:
753750
elif isinstance(other, int):
754751
div_frames = int(self.frames / other)
755752
else:
756-
raise TimecodeError(
757-
f"Type {other.__class__.__name__} not supported for arithmetic."
758-
)
753+
return NotImplemented
759754
tc = Timecode(self.framerate, frames=div_frames)
760755
tc._copy_props_from(self)
761756
return tc

tests/test_timecode.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,21 +1017,31 @@ def test_add_with_two_different_frame_rates():
10171017
[
10181018
[["24", "00:00:01:00"], {}, lambda x, y: x + y, "not suitable"],
10191019
[["24", "00:00:01:00"], {}, lambda x, y: x - y, "not suitable"],
1020-
[["24", "00:00:01:00"], {}, lambda x, y: x * y, "not suitable"],
10211020
[["24", "00:00:01:00"], {}, lambda x, y: x / y, "not suitable"],
10221021
[["24", "00:00:01:00"], {}, lambda x, y: x / y, 32.4],
1023-
],
1022+
[["24", "00:00:01:00"], {}, lambda x, y: x * y, 32.4],
1023+
]
10241024
)
1025-
def test_arithmetic_with_unsupported_type_raises_error(args, kwargs, func, tc2):
1026-
"""TimecodeError is raised if the other class is not suitable for the operation."""
1025+
def test_arithmetic_with_non_suitable_class_instance(args, kwargs, func, tc2):
1026+
"""TypeError is raised if the other class is not suitable for the operation."""
10271027
tc1 = Timecode(*args, **kwargs)
1028-
with pytest.raises(TimecodeError) as cm:
1028+
with pytest.raises(TypeError) as cm:
10291029
_ = func(tc1, tc2)
10301030

1031-
assert str(cm.value) == "Type {} not supported for arithmetic.".format(
1032-
tc2.__class__.__name__
1033-
)
1031+
assert str(cm.value).startswith(f"unsupported operand type(s) for")
1032+
assert str(cm.value).endswith(f"'Timecode' and '{tc2.__class__.__name__}'")
10341033

1034+
@pytest.mark.parametrize(
1035+
"args,kwargs,func,tc2", [
1036+
[["24", "00:00:01:00"], {}, lambda x, y: x * y, "not suitable"],
1037+
]
1038+
)
1039+
def test_multiply_with_sequence_type(args, kwargs, func, tc2):
1040+
"""TypeError is raised if the other class is not suitable for the operation."""
1041+
tc1 = Timecode(*args, **kwargs)
1042+
with pytest.raises(TypeError) as cm:
1043+
_ = func(tc1, tc2)
1044+
assert str(cm.value) == (f"can't multiply sequence by non-int of type 'Timecode'")
10351045

10361046
def test_div_method_working_properly_1():
10371047
"""__div__ method is working properly."""
@@ -1247,12 +1257,6 @@ def test_ms_vs_fraction_frames_2():
12471257

12481258

12491259
def test_ms_vs_fraction_frames_3():
1250-
tc1 = Timecode("ms", "00:00:00.040")
1251-
tc2 = Timecode(24, "00:00:00.042")
1252-
assert tc1 != tc2
1253-
1254-
1255-
def test_ms_vs_fraction_frames_4():
12561260
tc1 = Timecode("ms", "00:00:00.040")
12571261
tc2 = Timecode(24, "00:00:00.042")
12581262
assert tc1.frame_number == 40
@@ -1610,6 +1614,14 @@ def test_lt_method_with_integers():
16101614
tc = Timecode("24", "00:00:10:00")
16111615
assert tc < 250
16121616

1617+
def test_comparison_with_different_framerates_raises():
1618+
"""Comparing Timecodes with different framerates."""
1619+
tc1 = Timecode("24", "00:00:00:00")
1620+
tc2 = Timecode("30", "00:00:00:00")
1621+
with pytest.raises(ValueError) as cm:
1622+
_ = tc1 < tc2
1623+
_ = tc1 > tc2
1624+
16131625

16141626
def test_fraction_lib_from_python3_raises_import_error_for_python2():
16151627
"""ImportError is raised and the error is handled gracefully under Python 2 if

0 commit comments

Comments
 (0)