@@ -142,6 +142,48 @@ def mock_get_side_effect(url: str, **kwargs) -> Mock: # noqa: ARG001
142142 "enwiki-20230501-pages-articles-multistream1.xml.bz2"
143143 ]
144144
145+ @pytest .mark .parametrize ("transient_status" , [429 , 500 , 503 ])
146+ @patch ("requests.get" )
147+ def test_get_latest_dump_date_skips_transient_status_error (self , mock_get : Mock , transient_status : int ):
148+ """A transient status error for a candidate does not prevent fallback to an older dump."""
149+ mock_html = """
150+ <a href="20230501/">20230501/</a>
151+ <a href="20230601/">20230601/</a>
152+ """
153+ completed_dump = {
154+ "jobs" : {
155+ "articlesmultistreamdump" : {
156+ "status" : "done" ,
157+ "files" : {"enwiki-20230501-pages-articles-multistream1.xml.bz2" : {}},
158+ }
159+ }
160+ }
161+
162+ def mock_get_side_effect (url : str , ** kwargs ) -> Mock : # noqa: ARG001
163+ response = Mock (status_code = 200 )
164+ if url == "https://dumps.wikimedia.org/enwiki" :
165+ response .content = mock_html .encode ("utf-8" )
166+ elif url == "https://dumps.wikimedia.org/enwiki/20230601/dumpstatus.json" :
167+ response .status_code = transient_status
168+ response .raise_for_status .side_effect = requests .HTTPError (
169+ f"{ transient_status } Server Error" , response = response
170+ )
171+ elif url == "https://dumps.wikimedia.org/enwiki/20230501/dumpstatus.json" :
172+ response .content = json .dumps (completed_dump ).encode ("utf-8" )
173+ else :
174+ error_msg = f"Unexpected URL: { url } "
175+ raise ValueError (error_msg )
176+ return response
177+
178+ mock_get .side_effect = mock_get_side_effect
179+
180+ urls = WikipediaUrlGenerator (language = "en" ).generate_urls ()
181+
182+ assert urls == [
183+ "https://dumps.wikimedia.org/enwiki/20230501/"
184+ "enwiki-20230501-pages-articles-multistream1.xml.bz2"
185+ ]
186+
145187 @patch ("requests.get" )
146188 def test_get_latest_dump_date_http_error (self , mock_get : Mock ):
147189 """HTTP errors from the dump index are surfaced instead of parsed as HTML."""
0 commit comments