@@ -223,13 +223,28 @@ def norm_url(base: str, url: str) -> str:
223
223
"""
224
224
if "://" in url :
225
225
return url
226
- parts = urlsplit (urljoin (base , url ))
227
- path = normpath (parts [2 ])
228
- if sep != "/" :
229
- path = "/" .join (path .split (sep ))
230
- if parts [2 ].endswith ("/" ) and not path .endswith ("/" ):
231
- path += "/"
232
- result = urlunsplit (parts [0 :2 ] + (path ,) + parts [3 :])
226
+
227
+ # Fix for URNs
228
+ parsed_base = urlsplit (base )
229
+ parsed_url = urlsplit (url )
230
+ if parsed_url .scheme :
231
+ # Assume full URL
232
+ return url
233
+ if parsed_base .scheme in ("urn" , "urn-x" ):
234
+ # No scheme -> assume relative and join paths
235
+ base_path_parts = parsed_base .path .split ("/" , 1 )
236
+ base_path = "/" + (base_path_parts [1 ] if len (base_path_parts ) > 1 else "" )
237
+ joined_path = urljoin (base_path , parsed_url .path )
238
+ fragment = f"#{ parsed_url .fragment } " if parsed_url .fragment else ""
239
+ result = f"{ parsed_base .scheme } :{ base_path_parts [0 ]} { joined_path } { fragment } "
240
+ else :
241
+ parts = urlsplit (urljoin (base , url ))
242
+ path = normpath (parts [2 ])
243
+ if sep != "/" :
244
+ path = "/" .join (path .split (sep ))
245
+ if parts [2 ].endswith ("/" ) and not path .endswith ("/" ):
246
+ path += "/"
247
+ result = urlunsplit (parts [0 :2 ] + (path ,) + parts [3 :])
233
248
if url .endswith ("#" ) and not result .endswith ("#" ):
234
249
result += "#"
235
250
return result
0 commit comments