diff --git a/scalene/find_browser.py b/scalene/find_browser.py index 5c25ff8a4..dca9bff67 100644 --- a/scalene/find_browser.py +++ b/scalene/find_browser.py @@ -21,7 +21,7 @@ def find_browser(browserClass: Optional[str] = None) -> Optional[str]: # we need to refer to it as such to prevent this error: # 'MacOSXOSAScript' object has no attribute 'name' browser = webbrowser.get(browserClass) - return browser._name if browser._name not in text_browsers else None + return browser._name if browser._name not in text_browsers else None # type: ignore[attr-defined] except webbrowser.Error: # Return None if there is an error in getting the browser return None diff --git a/scalene/scalene_config.py b/scalene/scalene_config.py index ef8f42b7e..bf5c59114 100644 --- a/scalene/scalene_config.py +++ b/scalene/scalene_config.py @@ -1,7 +1,7 @@ """Current version of Scalene; reported by --version.""" -scalene_version = "1.5.42.2" -scalene_date = "2024.06.18" +scalene_version = "1.5.42.3" +scalene_date = "2024.07.05" # Port to use for Scalene UI SCALENE_PORT = 11235 diff --git a/scalene/scalene_profiler.py b/scalene/scalene_profiler.py index 7777e0fd3..31cc7836d 100644 --- a/scalene/scalene_profiler.py +++ b/scalene/scalene_profiler.py @@ -101,11 +101,6 @@ if sys.platform != "win32": import resource -if platform.system() == "Darwin": - from scalene.scalene_apple_gpu import ScaleneAppleGPU as ScaleneGPU -else: - from scalene.scalene_gpu import ScaleneGPU # type: ignore - from scalene.scalene_parseargs import ScaleneParseArgs, StopJupyterExecution from scalene.scalene_sigqueue import ScaleneSigQueue @@ -214,10 +209,7 @@ def last_profiled_tuple() -> Tuple[Filename, LineNumber, ByteCodeIndex]: __stats = ScaleneStatistics() __output = ScaleneOutput() __json = ScaleneJSON() - __gpu = ScaleneGPU() - - __output.gpu = __gpu.has_gpu() - __json.gpu = __gpu.has_gpu() + __gpu = None # initialized after parsing arguments in `main` __invalidate_queue: List[Tuple[Filename, LineNumber]] = [] __invalidate_mutex: threading.Lock __profiler_base: str @@ -762,7 +754,10 @@ def cpu_signal_handler( ) return - (gpu_load, gpu_mem_used) = Scalene.__gpu.get_stats() + if Scalene.__gpu: + (gpu_load, gpu_mem_used) = Scalene.__gpu.get_stats() + else: + (gpu_load, gpu_mem_used) = (0.0, 0.0) # Process this CPU sample. Scalene.process_cpu_sample( @@ -1442,7 +1437,7 @@ def after_fork_in_child() -> None: Scalene.__is_child = True Scalene.clear_metrics() - if Scalene.__gpu.has_gpu(): + if Scalene.__gpu and Scalene.__gpu.has_gpu(): Scalene.__gpu.nvml_reinit() # Note: __parent_pid of the topmost process is its own pid. Scalene.__pid = Scalene.__parent_pid @@ -1887,6 +1882,19 @@ def main() -> None: args, left, ) = ScaleneParseArgs.parse_args() + # Try to profile a GPU if one is found and `--gpu` is selected / it's the default (see ScaleneArguments). + if args.gpu: + if platform.system() == "Darwin": + from scalene.scalene_apple_gpu import ScaleneAppleGPU as ScaleneGPU + else: + from scalene.scalene_gpu import ScaleneGPU # type: ignore + Scalene.__gpu = ScaleneGPU() + Scalene.__output.gpu = Scalene.__gpu.has_gpu() + Scalene.__json.gpu = Scalene.__gpu.has_gpu() + else: + Scalene.__gpu = None + Scalene.__output.gpu = False + Scalene.__json.gpu = False Scalene.set_initialized() Scalene.run_profiler(args, left) diff --git a/tests/test_coverup_58.py b/tests/test_coverup_58.py deleted file mode 100644 index faaa46ac4..000000000 --- a/tests/test_coverup_58.py +++ /dev/null @@ -1,94 +0,0 @@ -# file scalene/get_module_details.py:21-94 -# lines [21, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 37, 38, 40, 42, 43, 44, 46, 47, 50, 52, 54, 55, 56, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94] -# branches ['26->27', '26->28', '29->31', '29->54', '37->40', '37->42', '43->44', '43->54', '61->62', '61->66', '67->68', '67->69', '69->70', '69->82', '70->71', '70->72', '76->77', '76->78', '84->85', '84->88', '92->93', '92->94'] - -import importlib.util -import sys -from types import ModuleType -from importlib.abc import SourceLoader -from importlib.machinery import ModuleSpec -from types import CodeType -from typing import Tuple, Type -import pytest - -class MockLoader(SourceLoader): - def get_code(self, fullname): - if fullname == "no_code_object": - return None - return compile("", "", "exec") - - def get_source(self, fullname): - return "" - - def get_data(self, path): - return b'' - - def get_filename(self, fullname): - return "" - -def test_get_module_details_relative_name_error(): - from scalene.get_module_details import _get_module_details - with pytest.raises(ImportError): - _get_module_details(".relative") - -def test_get_module_details_namespace_package_error(): - from scalene.get_module_details import _get_module_details - mod_name = "namespace_package" - spec = ModuleSpec(name=mod_name, loader=None, origin="namespace origin") - sys.modules[mod_name] = ModuleType(mod_name) - sys.modules[mod_name].__spec__ = spec - with pytest.raises(ImportError): - _get_module_details(mod_name) - del sys.modules[mod_name] - -def test_get_module_details_no_code_object_error(): - from scalene.get_module_details import _get_module_details - mod_name = "no_code_object" - spec = ModuleSpec(name=mod_name, loader=MockLoader(), origin="no code origin") - sys.modules[mod_name] = ModuleType(mod_name) - sys.modules[mod_name].__spec__ = spec - with pytest.raises(ImportError): - _get_module_details(mod_name) - del sys.modules[mod_name] - -def test_get_module_details_package_as_main_error(): - from scalene.get_module_details import _get_module_details - mod_name = "__main__" - spec = ModuleSpec(name=mod_name, loader=MockLoader(), origin="main origin") - spec.submodule_search_locations = [] - sys.modules[mod_name] = ModuleType(mod_name) - sys.modules[mod_name].__spec__ = spec - with pytest.raises(ImportError): - _get_module_details(mod_name) - del sys.modules[mod_name] - -def test_get_module_details_already_imported_warning(): - from scalene.get_module_details import _get_module_details - mod_name = "already.imported" - pkg_name = "already" - sys.modules[pkg_name] = ModuleType(pkg_name) - sys.modules[mod_name] = ModuleType(mod_name) - spec = ModuleSpec(name=mod_name, loader=MockLoader(), origin="already imported origin") - sys.modules[mod_name].__spec__ = spec - with pytest.warns(RuntimeWarning): - _get_module_details(mod_name) - del sys.modules[mod_name] - del sys.modules[pkg_name] - -def test_get_module_details_find_spec_error(): - from scalene.get_module_details import _get_module_details - mod_name = "nonexistent.module" - with pytest.raises(ImportError): - _get_module_details(mod_name) - -def test_get_module_details_success(): - from scalene.get_module_details import _get_module_details - mod_name = "successful.module" - spec = ModuleSpec(name=mod_name, loader=MockLoader(), origin="success origin") - sys.modules[mod_name] = ModuleType(mod_name) - sys.modules[mod_name].__spec__ = spec - result_mod_name, result_spec, result_code = _get_module_details(mod_name) - assert result_mod_name == mod_name - assert result_spec == spec - assert isinstance(result_code, CodeType) - del sys.modules[mod_name]