@@ -114,6 +114,10 @@ class URI:
114114 "hdfs" ,
115115 )
116116
117+ # ``file://`` authorities that denote the local machine (RFC 8089 §2):
118+ # an empty authority (``file:///path``) or the special ``localhost`` host.
119+ LOCAL_FILE_AUTHORITIES = ("" , "localhost" )
120+
117121 # Backwards-compatible alias kept for callers that still inspect it.
118122 REMOTE_SUPPORTED_SCHEMA = SUPPORTED_ROCRATE_SCHEMES [:- 1 ] # http, https, ftp
119123
@@ -123,12 +127,20 @@ def __init__(self, uri: Union[str, Path]):
123127 self ._uri = uri = str (uri )
124128 try :
125129 # Inputs that are not external references are assumed to be local
126- # paths, so the ``file:// `` scheme is added explicitly. The
130+ # paths, so the ``file:`` scheme is added explicitly. The
127131 # detection covers both authority-based schemes (``http://``,
128132 # ``scp://``) and scheme-only ones (``urn:``, ``doi:``), as
129133 # defined by RFC 3986.
134+ #
135+ # The authority-less ``file:`` form (no ``//``) is used on purpose:
136+ # ``file://data/x`` would parse ``data`` as the authority (host),
137+ # while ``file:data/x`` keeps ``data/x`` as the path with an empty
138+ # authority. This way a local path never gains a spurious host and
139+ # the authority remains a reliable signal to tell a local file
140+ # (``file:///path``) from a remote one (``file://host/path``,
141+ # RFC 8089).
130142 if not is_external_reference (uri ):
131- uri = f"file:// { uri } "
143+ uri = f"file:{ uri } "
132144 # parse the value to extract the scheme
133145 self ._parse_result = urlparse (uri )
134146 if not self .scheme :
@@ -181,11 +193,23 @@ def as_path(self) -> Path:
181193 return Path (self ._uri )
182194
183195 def is_remote_resource (self ) -> bool :
184- """Return True for any well-formed URI whose scheme is not `file`."""
185- return bool (self .scheme ) and self .scheme != "file"
196+ """
197+ Return True for any well-formed URI that points to a non-local resource.
198+
199+ Schemes other than ``file`` (``http``, ``scp``, ``s3``, ...) are always
200+ remote. A ``file://`` URI is remote when it carries an explicit,
201+ non-local authority (host) — e.g. ``file://hostname/path`` per
202+ RFC 8089: the referenced file lives on another machine and is therefore
203+ not part of the local RO-Crate payload.
204+ """
205+ if not self .scheme :
206+ return False
207+ if self .scheme == "file" :
208+ return self .get_netloc ().lower () not in self .LOCAL_FILE_AUTHORITIES
209+ return True
186210
187211 def is_local_resource (self ) -> bool :
188- return self .scheme == "file"
212+ return self .scheme == "file" and self . get_netloc (). lower () in self . LOCAL_FILE_AUTHORITIES
189213
190214 def is_natively_checkable (self ) -> bool :
191215 """Return True if availability can be verified via a native request."""
0 commit comments