@@ -173,20 +173,32 @@ def relative_file_path(self) -> str:
173
173
174
174
If the relative file path cannot be determined, the value returned is `""` (empty string).
175
175
"""
176
- top_package_name = self .path .split ("." , 1 )[0 ]
177
- try :
178
- top_package = sys .modules [top_package_name ]
179
- except KeyError :
176
+
177
+ parts = self .path .split ("." )
178
+ namespaces = ["." .join (parts [:l ]) for l in range (1 , len (parts ) + 1 )]
179
+ # Iterate through all sub namespaces including the last in case it is a module
180
+ for namespace in namespaces :
181
+ try :
182
+ importlib .import_module (namespace )
183
+ top_package = sys .modules [namespace ]
184
+ except (ImportError , ModuleNotFoundError , KeyError ):
185
+ # ImportError: Triggered if the namespace is not importable
186
+ # ModuleNotFoundError: Triggered if the namespace is not a module
187
+ # KeyError: Triggered if the imported package isn't referenced under the same fully qualified name
188
+ # Namespace packages are importable, so this should work for them
189
+ return ""
190
+
180
191
try :
181
- importlib .import_module (top_package_name )
182
- except ImportError :
192
+ top_package_path = Path (inspect .getabsfile (top_package )).parent
193
+ return str (Path (self .file_path ).relative_to (top_package_path .parent ))
194
+ except TypeError :
195
+ # Triggered if getabsfile() can't be found in the case of a Namespace package
196
+ pass
197
+ except ValueError :
198
+ # Triggered if Path().relative_to can't find an appropriate path
183
199
return ""
184
- top_package = sys .modules [top_package_name ]
185
- top_package_path = Path (inspect .getabsfile (top_package )).parent
186
- try :
187
- return str (Path (self .file_path ).relative_to (top_package_path .parent ))
188
- except ValueError :
189
- return ""
200
+
201
+ return ""
190
202
191
203
@property
192
204
def name_to_check (self ) -> str :
0 commit comments