2525
2626# Standard Library Imports
2727from scenedetect .common import MAX_FPS_DELTA , FrameTimecode
28+ from fractions import Fraction
2829
2930
3031def test_framerate ():
@@ -38,11 +39,11 @@ def test_framerate():
3839 FrameTimecode (timecode = None , fps = FrameTimecode (timecode = 0 , fps = None ))
3940 # Test zero FPS/negative.
4041 with pytest .raises (ValueError ):
41- FrameTimecode (timecode = 0 , fps = 0 )
42+ FrameTimecode (timecode = 0 , fps = 0.0 )
4243 with pytest .raises (ValueError ):
43- FrameTimecode (timecode = 0 , fps = - 1 )
44+ FrameTimecode (timecode = 0 , fps = - 1.0 )
4445 with pytest .raises (ValueError ):
45- FrameTimecode (timecode = 0 , fps = - 100 )
46+ FrameTimecode (timecode = 0 , fps = - 100.0 )
4647 with pytest .raises (ValueError ):
4748 FrameTimecode (timecode = 0 , fps = 0.0 )
4849 with pytest .raises (ValueError ):
@@ -52,26 +53,28 @@ def test_framerate():
5253 with pytest .raises (ValueError ):
5354 FrameTimecode (timecode = 0 , fps = MAX_FPS_DELTA / 2 )
5455 # Test positive framerates.
55- assert FrameTimecode (timecode = 0 , fps = 1 ).frame_num == 0
56- assert FrameTimecode (timecode = 0 , fps = MAX_FPS_DELTA ).frame_num == 0
57- assert FrameTimecode (timecode = 0 , fps = 10 ).frame_num == 0
56+ assert FrameTimecode (timecode = 0 , fps = 1.0 ).frame_num == 0
57+ assert FrameTimecode (timecode = 0 , fps = 10.0 ).frame_num == 0
5858 assert FrameTimecode (timecode = 0 , fps = MAX_FPS_DELTA * 2 ).frame_num == 0
59- assert FrameTimecode (timecode = 0 , fps = 1000 ).frame_num == 0
6059 assert FrameTimecode (timecode = 0 , fps = 1000.0 ).frame_num == 0
60+ assert FrameTimecode (timecode = 0 , fps = 1000.0 ).frame_num == 0
61+ # Reject framerates too small for equality testing or potential divide by zero situations.
62+ with pytest .raises (ValueError ):
63+ assert FrameTimecode (timecode = 0 , fps = MAX_FPS_DELTA ).frame_num == 0
6164
6265
6366def test_timecode_numeric ():
6467 """Test FrameTimecode constructor argument "timecode" with numeric arguments."""
6568 with pytest .raises (ValueError ):
66- FrameTimecode (timecode = - 1 , fps = 1 )
69+ FrameTimecode (timecode = - 1 , fps = 1.0 )
6770 with pytest .raises (ValueError ):
6871 FrameTimecode (timecode = - 1.0 , fps = 1.0 )
6972 with pytest .raises (ValueError ):
7073 FrameTimecode (timecode = - 0.1 , fps = 1.0 )
7174 with pytest .raises (ValueError ):
7275 FrameTimecode (timecode = - 1.0 / 1000 , fps = 1.0 )
73- assert FrameTimecode (timecode = 0 , fps = 1 ).frame_num == 0
74- assert FrameTimecode (timecode = 1 , fps = 1 ).frame_num == 1
76+ assert FrameTimecode (timecode = 0 , fps = 1.0 ).frame_num == 0
77+ assert FrameTimecode (timecode = 1 , fps = 1.0 ).frame_num == 1
7578 assert FrameTimecode (timecode = 0.0 , fps = 1.0 ).frame_num == 0
7679 assert FrameTimecode (timecode = 1.0 , fps = 1.0 ).frame_num == 1
7780
@@ -80,13 +83,13 @@ def test_timecode_string():
8083 """Test FrameTimecode constructor argument "timecode" with string arguments."""
8184 # Invalid strings:
8285 with pytest .raises (ValueError ):
83- FrameTimecode (timecode = "-1" , fps = 1 )
86+ FrameTimecode (timecode = "-1" , fps = 1.0 )
8487 with pytest .raises (ValueError ):
8588 FrameTimecode (timecode = "-1.0" , fps = 1.0 )
8689 with pytest .raises (ValueError ):
8790 FrameTimecode (timecode = "-0.1" , fps = 1.0 )
8891 with pytest .raises (ValueError ):
89- FrameTimecode (timecode = "1.9x" , fps = 1 )
92+ FrameTimecode (timecode = "1.9x" , fps = 1.0 )
9093 with pytest .raises (ValueError ):
9194 FrameTimecode (timecode = "1x" , fps = 1.0 )
9295 with pytest .raises (ValueError ):
@@ -95,56 +98,56 @@ def test_timecode_string():
9598 FrameTimecode (timecode = "1.0-" , fps = 1.0 )
9699
97100 # Frame number integer [int->str] ('%d', integer number as string)
98- assert FrameTimecode (timecode = "0" , fps = 1 ).frame_num == 0
99- assert FrameTimecode (timecode = "1" , fps = 1 ).frame_num == 1
101+ assert FrameTimecode (timecode = "0" , fps = 1.0 ).frame_num == 0
102+ assert FrameTimecode (timecode = "1" , fps = 1.0 ).frame_num == 1
100103 assert FrameTimecode (timecode = "10" , fps = 1.0 ).frame_num == 10
101104
102105 # Seconds format [float->str] ('%f', number as string)
103- assert FrameTimecode (timecode = "0.0" , fps = 1 ).frame_num == 0
104- assert FrameTimecode (timecode = "1.0" , fps = 1 ).frame_num == 1
106+ assert FrameTimecode (timecode = "0.0" , fps = 1.0 ).frame_num == 0
107+ assert FrameTimecode (timecode = "1.0" , fps = 1.0 ).frame_num == 1
105108 assert FrameTimecode (timecode = "10.0" , fps = 1.0 ).frame_num == 10
106109 assert FrameTimecode (timecode = "10.0000000000" , fps = 1.0 ).frame_num == 10
107110 assert FrameTimecode (timecode = "10.100" , fps = 1.0 ).frame_num == 10
108111 assert FrameTimecode (timecode = "1.100" , fps = 10.0 ).frame_num == 11
109112
110113 # Seconds format [float->str] ('%fs', number as string followed by 's' for seconds)
111- assert FrameTimecode (timecode = "0s" , fps = 1 ).frame_num == 0
112- assert FrameTimecode (timecode = "1s" , fps = 1 ).frame_num == 1
114+ assert FrameTimecode (timecode = "0s" , fps = 1.0 ).frame_num == 0
115+ assert FrameTimecode (timecode = "1s" , fps = 1.0 ).frame_num == 1
113116 assert FrameTimecode (timecode = "10s" , fps = 1.0 ).frame_num == 10
114117 assert FrameTimecode (timecode = "10.0s" , fps = 1.0 ).frame_num == 10
115118 assert FrameTimecode (timecode = "10.0000000000s" , fps = 1.0 ).frame_num == 10
116119 assert FrameTimecode (timecode = "10.100s" , fps = 1.0 ).frame_num == 10
117120 assert FrameTimecode (timecode = "1.100s" , fps = 10.0 ).frame_num == 11
118121
119122 # Standard timecode format [timecode->str] ('HH:MM:SS[.nnn]', where [.nnn] is optional)
120- assert FrameTimecode (timecode = "00:00:01" , fps = 1 ).frame_num == 1
121- assert FrameTimecode (timecode = "00:00:01.9999" , fps = 1 ).frame_num == 2
122- assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1 ).frame_num == 2
123- assert FrameTimecode (timecode = "00:00:02.0001" , fps = 1 ).frame_num == 2
123+ assert FrameTimecode (timecode = "00:00:01" , fps = 1.0 ).frame_num == 1
124+ assert FrameTimecode (timecode = "00:00:01.9999" , fps = 1.0 ).frame_num == 2
125+ assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1.0 ).frame_num == 2
126+ assert FrameTimecode (timecode = "00:00:02.0001" , fps = 1.0 ).frame_num == 2
124127
125128 # MM:SS[.nnn] is also allowed
126- assert FrameTimecode (timecode = "00:01" , fps = 1 ).frame_num == 1
127- assert FrameTimecode (timecode = "00:01.9999" , fps = 1 ).frame_num == 2
128- assert FrameTimecode (timecode = "00:02.0000" , fps = 1 ).frame_num == 2
129- assert FrameTimecode (timecode = "00:02.0001" , fps = 1 ).frame_num == 2
129+ assert FrameTimecode (timecode = "00:01" , fps = 1.0 ).frame_num == 1
130+ assert FrameTimecode (timecode = "00:01.9999" , fps = 1.0 ).frame_num == 2
131+ assert FrameTimecode (timecode = "00:02.0000" , fps = 1.0 ).frame_num == 2
132+ assert FrameTimecode (timecode = "00:02.0001" , fps = 1.0 ).frame_num == 2
130133
131134 # Conversion edge cases
132- assert FrameTimecode (timecode = "00:00:01" , fps = 10 ).frame_num == 10
133- assert FrameTimecode (timecode = "00:00:00.5" , fps = 10 ).frame_num == 5
134- assert FrameTimecode (timecode = "00:00:00.100" , fps = 10 ).frame_num == 1
135- assert FrameTimecode (timecode = "00:00:00.001" , fps = 1000 ).frame_num == 1
135+ assert FrameTimecode (timecode = "00:00:01" , fps = 10.0 ).frame_num == 10
136+ assert FrameTimecode (timecode = "00:00:00.5" , fps = 10.0 ).frame_num == 5
137+ assert FrameTimecode (timecode = "00:00:00.100" , fps = 10.0 ).frame_num == 1
138+ assert FrameTimecode (timecode = "00:00:00.001" , fps = 1000.0 ).frame_num == 1
136139
137- assert FrameTimecode (timecode = "00:00:59.999" , fps = 1 ).frame_num == 60
138- assert FrameTimecode (timecode = "00:01:00.000" , fps = 1 ).frame_num == 60
139- assert FrameTimecode (timecode = "00:01:00.001" , fps = 1 ).frame_num == 60
140+ assert FrameTimecode (timecode = "00:00:59.999" , fps = 1.0 ).frame_num == 60
141+ assert FrameTimecode (timecode = "00:01:00.000" , fps = 1.0 ).frame_num == 60
142+ assert FrameTimecode (timecode = "00:01:00.001" , fps = 1.0 ).frame_num == 60
140143
141- assert FrameTimecode (timecode = "00:59:59.999" , fps = 1 ).frame_num == 3600
142- assert FrameTimecode (timecode = "01:00:00.000" , fps = 1 ).frame_num == 3600
143- assert FrameTimecode (timecode = "01:00:00.001" , fps = 1 ).frame_num == 3600
144+ assert FrameTimecode (timecode = "00:59:59.999" , fps = 1.0 ).frame_num == 3600
145+ assert FrameTimecode (timecode = "01:00:00.000" , fps = 1.0 ).frame_num == 3600
146+ assert FrameTimecode (timecode = "01:00:00.001" , fps = 1.0 ).frame_num == 3600
144147
145148 # Check too many ":" characters (https://github.com/Breakthrough/PySceneDetect/issues/476)
146149 with pytest .raises (ValueError ):
147- FrameTimecode (timecode = "01:01:00:00.001" , fps = 1 )
150+ FrameTimecode (timecode = "01:01:00:00.001" , fps = 1.0 )
148151
149152
150153def test_get_frames ():
@@ -157,10 +160,10 @@ def test_get_frames():
157160 assert FrameTimecode (timecode = 1000.0 , fps = 60.0 ).frame_num == int (1000.0 * 60.0 )
158161 assert FrameTimecode (timecode = 1000000000.0 , fps = 29.97 ).frame_num == int (1000000000.0 * 29.97 )
159162
160- assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1 ).frame_num == 2
161- assert FrameTimecode (timecode = "00:00:00.5" , fps = 10 ).frame_num == 5
162- assert FrameTimecode (timecode = "00:00:01" , fps = 10 ).frame_num == 10
163- assert FrameTimecode (timecode = "00:01:00.000" , fps = 1 ).frame_num == 60
163+ assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1.0 ).frame_num == 2
164+ assert FrameTimecode (timecode = "00:00:00.5" , fps = 10.0 ).frame_num == 5
165+ assert FrameTimecode (timecode = "00:00:01" , fps = 10.0 ).frame_num == 10
166+ assert FrameTimecode (timecode = "00:01:00.000" , fps = 1.0 ).frame_num == 60
164167
165168
166169def test_get_seconds ():
@@ -173,10 +176,10 @@ def test_get_seconds():
173176 assert FrameTimecode (timecode = 1000.0 , fps = 60.0 ).seconds , pytest .approx (1000.0 )
174177 assert FrameTimecode (timecode = 1000000000.0 , fps = 29.97 ).seconds , pytest .approx (1000000000.0 )
175178
176- assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1 ).seconds , pytest .approx (2.0 )
177- assert FrameTimecode (timecode = "00:00:00.5" , fps = 10 ).seconds , pytest .approx (0.5 )
178- assert FrameTimecode (timecode = "00:00:01" , fps = 10 ).seconds , pytest .approx (1.0 )
179- assert FrameTimecode (timecode = "00:01:00.000" , fps = 1 ).seconds , pytest .approx (60.0 )
179+ assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1.0 ).seconds , pytest .approx (2.0 )
180+ assert FrameTimecode (timecode = "00:00:00.5" , fps = 10.0 ).seconds , pytest .approx (0.5 )
181+ assert FrameTimecode (timecode = "00:00:01" , fps = 10.0 ).seconds , pytest .approx (1.0 )
182+ assert FrameTimecode (timecode = "00:01:00.000" , fps = 1.0 ).seconds , pytest .approx (60.0 )
180183
181184
182185def test_get_timecode ():
@@ -185,15 +188,15 @@ def test_get_timecode():
185188 assert FrameTimecode (timecode = 60.117 , fps = 60.0 ).get_timecode () == "00:01:00.117"
186189 assert FrameTimecode (timecode = 3600.234 , fps = 29.97 ).get_timecode () == "01:00:00.234"
187190
188- assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1 ).get_timecode () == "00:00:02.000"
189- assert FrameTimecode (timecode = "00:00:00.5" , fps = 10 ).get_timecode () == "00:00:00.500"
191+ assert FrameTimecode (timecode = "00:00:02.0000" , fps = 1.0 ).get_timecode () == "00:00:02.000"
192+ assert FrameTimecode (timecode = "00:00:00.5" , fps = 10.0 ).get_timecode () == "00:00:00.500"
190193 # If a value is provided in seconds, we store that value internally now.
191194 assert (
192- FrameTimecode (timecode = "00:00:01.501" , fps = 10 ).get_timecode (nearest_frame = False )
195+ FrameTimecode (timecode = "00:00:01.501" , fps = 10.0 ).get_timecode (nearest_frame = False )
193196 == "00:00:01.501"
194197 )
195198 assert (
196- FrameTimecode (timecode = "00:00:01.501" , fps = 10 ).get_timecode (nearest_frame = True )
199+ FrameTimecode (timecode = "00:00:01.501" , fps = 10.0 ).get_timecode (nearest_frame = True )
197200 == "00:00:01.500"
198201 )
199202
@@ -204,8 +207,10 @@ def test_equality():
204207 assert x == x
205208 assert x == FrameTimecode (timecode = 1.0 , fps = 10.0 )
206209 assert x == FrameTimecode (timecode = 1.0 , fps = 10.0 )
210+ assert x == FrameTimecode (timecode = 1.0 , fps = Fraction (10 , 1 ))
207211 assert x != FrameTimecode (timecode = 10.0 , fps = 10.0 )
208212 assert x != FrameTimecode (timecode = 10.0 , fps = 10.0 )
213+ assert x != FrameTimecode (timecode = 10.0 , fps = Fraction (100 , 10 ))
209214 assert x == FrameTimecode (x )
210215 assert x == FrameTimecode (1.0 , x )
211216 assert x == FrameTimecode (10 , x )
@@ -231,8 +236,8 @@ def test_equality():
231236 with pytest .raises (TypeError ):
232237 assert x == {0 : 0 }
233238
234- assert FrameTimecode (timecode = "00:00:00.5" , fps = 10 ) == "00:00:00.500"
235- assert FrameTimecode (timecode = "00:00:01.500" , fps = 10 ) == "00:00:01.500"
239+ assert FrameTimecode (timecode = "00:00:00.5" , fps = 10.0 ) == "00:00:00.500"
240+ assert FrameTimecode (timecode = "00:00:01.500" , fps = 10.0 ) == "00:00:01.500"
236241
237242
238243def test_addition ():
@@ -261,7 +266,9 @@ def test_subtraction():
261266 assert FrameTimecode ("00:00:00.000" , fps = 20.0 ) == x - 10
262267
263268
264- @pytest .mark .parametrize ("frame_num,fps" , [(1 , 1 ), (61 , 14 ), (29 , 25 ), (126 , 24000 / 1001.0 )])
269+ @pytest .mark .parametrize (
270+ "frame_num,fps" , [(1 , 1.0 ), (61 , 14.0 ), (29 , 25.0 ), (126 , Fraction (24000 , 1001 ))]
271+ )
265272def test_identity (frame_num , fps ):
266273 """Test FrameTimecode values, when used in init return the same values"""
267274 frame_time_code = FrameTimecode (frame_num , fps = fps )
0 commit comments