66
77import pytest
88
9+ from datamodel_code_generator .http import join_url
910from datamodel_code_generator .reference import ModelResolver , get_relative_path , is_url
1011
1112
@@ -171,12 +172,15 @@ def test_resolve_ref_local_fragment_with_base_url() -> None:
171172@pytest .mark .parametrize (
172173 ("ref" , "expected" ),
173174 [
174- # HTTP/HTTPS URLs (only supported schemes)
175+ # HTTP/HTTPS URLs
175176 ("https://example.com/schema.json" , True ),
176177 ("http://example.com/schema.json" , True ),
177178 ("https://example.com/path/to/schema.json" , True ),
178- # file:// URLs - NOT recognized (fetcher only supports HTTP)
179- ("file:///home/user/schema.json" , False ),
179+ # file:// URLs - recognized and handled via filesystem
180+ ("file:///home/user/schema.json" , True ),
181+ ("file:///C:/path/to/schema.json" , True ),
182+ ("file://server/share/schema.json" , True ),
183+ # file:/ (single slash) - NOT recognized as valid file URL
180184 ("file:/home/user/schema.json" , False ),
181185 # Other URL schemes - NOT recognized
182186 ("ftp://example.com/schema.json" , False ),
@@ -194,7 +198,7 @@ def test_resolve_ref_local_fragment_with_base_url() -> None:
194198 ],
195199)
196200def test_is_url (ref : str , expected : bool ) -> None :
197- """Test is_url correctly identifies HTTP(S) URLs only ."""
201+ """Test is_url correctly identifies HTTP(S) and file:// URLs ."""
198202 assert is_url (ref ) == expected
199203
200204
@@ -207,3 +211,52 @@ def test_resolve_ref_with_root_id_differs_from_base_url() -> None:
207211 result = resolver .resolve_ref ("../common/types.json" )
208212
209213 assert result == "https://example.com/common/types.json#"
214+
215+
216+ @pytest .mark .parametrize (
217+ ("base_url" , "ref" , "expected" ),
218+ [
219+ # file:// URL joining - relative refs
220+ ("file:///home/user/schemas/main.json" , "../common/types.json" , "file:///home/user/common/types.json" ),
221+ ("file:///home/user/schemas/main.json" , "other.json" , "file:///home/user/schemas/other.json" ),
222+ ("file:///home/user/schemas/main.json" , "./sub/schema.json" , "file:///home/user/schemas/sub/schema.json" ),
223+ # file:// URL joining - absolute file:// refs
224+ ("file:///home/user/schemas/main.json" , "file:///other/schema.json" , "file:///other/schema.json" ),
225+ # file:// URL joining - absolute path refs (starts with /)
226+ ("file:///home/user/schemas/main.json" , "/absolute/path.json" , "file:///absolute/path.json" ),
227+ ("file://server/share/main.json" , "/absolute/path.json" , "file://server/absolute/path.json" ),
228+ # Windows-style file:// URLs
229+ ("file:///C:/schemas/main.json" , "../common/types.json" , "file:///C:/common/types.json" ),
230+ # UNC file:// URLs
231+ ("file://server/share/main.json" , "../common/types.json" , "file://server/share/common/types.json" ),
232+ ("file://server/share/main.json" , "child.json" , "file://server/share/child.json" ),
233+ # Fragment handling
234+ (
235+ "file:///home/user/schemas/main.json" ,
236+ "other.json#/definitions/Foo" ,
237+ "file:///home/user/schemas/other.json#/definitions/Foo" ,
238+ ),
239+ (
240+ "file:///home/user/schemas/main.json" ,
241+ "#/definitions/Bar" ,
242+ "file:///home/user/schemas/main.json#/definitions/Bar" ,
243+ ),
244+ # Multiple .. traversal - stops at root for non-UNC
245+ ("file:///a/b/main.json" , "../../../other.json" , "file:///other.json" ),
246+ # Multiple .. traversal - stops at share level for UNC (min_depth=1)
247+ ("file://server/share/a/b/main.json" , "../../../../other.json" , "file://server/share/other.json" ),
248+ # Empty and dot segments
249+ ("file:///home/user/schemas/main.json" , "./" , "file:///home/user/schemas/" ),
250+ ("file:///home/user/schemas/main.json" , "a//b/./c.json" , "file:///home/user/schemas/a/b/c.json" ),
251+ # Fragment-only ref without fragment content (just #)
252+ ("file:///home/user/schemas/main.json" , "#" , "file:///home/user/schemas/main.json#" ),
253+ # Empty ref (keeps base URL unchanged)
254+ ("file:///home/user/schemas/main.json" , "" , "file:///home/user/schemas/main.json" ),
255+ # Root directory base URL (triggers empty base_segments branch)
256+ ("file:///" , "schema.json" , "file:///schema.json" ),
257+ ("file:///main.json" , "../other.json" , "file:///other.json" ),
258+ ],
259+ )
260+ def test_join_url_file_scheme (base_url : str , ref : str , expected : str ) -> None :
261+ """Test join_url correctly handles file:// URLs."""
262+ assert join_url (base_url , ref ) == expected
0 commit comments