@@ -249,10 +249,10 @@ def __init__( # pylint: disable=too-many-arguments
249
249
# Other instance attributes, set with placebos or placeholders.
250
250
# More useful objects will be created later.
251
251
self ._debug : DebugControl = NoDebugging ()
252
- self ._inorout : InOrOut = _InOrOutPlacebo ()
252
+ self ._inorout : Optional [ InOrOut ] = None
253
253
self ._plugins : Plugins = Plugins ()
254
- self ._data : CoverageData = _CoverageDataPlacebo ()
255
- self ._collector : Collector = _CollectorPlacebo ()
254
+ self ._data : Optional [ CoverageData ] = None
255
+ self ._collector : Optional [ Collector ] = None
256
256
257
257
self ._file_mapper : Callable [[str ], str ] = abs_file
258
258
self ._data_suffix = self ._run_suffix = None
@@ -378,6 +378,7 @@ def _should_trace(self, filename: str, frame: FrameType) -> TFileDisposition:
378
378
Calls `_should_trace_internal`, and returns the FileDisposition.
379
379
380
380
"""
381
+ assert self ._inorout is not None
381
382
disp = self ._inorout .should_trace (filename , frame )
382
383
if self ._debug .should ('trace' ):
383
384
self ._debug .write (disposition_debug_msg (disp ))
@@ -389,6 +390,7 @@ def _check_include_omit_etc(self, filename: str, frame: FrameType) -> bool:
389
390
Returns a boolean: True if the file should be traced, False if not.
390
391
391
392
"""
393
+ assert self ._inorout is not None
392
394
reason = self ._inorout .check_include_omit_etc (filename , frame )
393
395
if self ._debug .should ('trace' ):
394
396
if not reason :
@@ -484,12 +486,14 @@ def set_option(self, option_name: str, value: Union[TConfigValueIn, TConfigSecti
484
486
def load (self ) -> None :
485
487
"""Load previously-collected coverage data from the data file."""
486
488
self ._init ()
487
- self ._collector .reset ()
489
+ if self ._collector is not None :
490
+ self ._collector .reset ()
488
491
should_skip = self .config .parallel and not os .path .exists (self .config .data_file )
489
492
if not should_skip :
490
493
self ._init_data (suffix = None )
491
494
self ._post_init ()
492
495
if not should_skip :
496
+ assert self ._data is not None
493
497
self ._data .read ()
494
498
495
499
def _init_for_start (self ) -> None :
@@ -541,6 +545,7 @@ def _init_for_start(self) -> None:
541
545
542
546
self ._init_data (suffix )
543
547
548
+ assert self ._data is not None
544
549
self ._collector .use_data (self ._data , self .config .context )
545
550
546
551
# Early warning if we aren't going to be able to support plugins.
@@ -584,7 +589,7 @@ def _init_for_start(self) -> None:
584
589
585
590
def _init_data (self , suffix : Optional [Union [str , bool ]]) -> None :
586
591
"""Create a data file if we don't have one yet."""
587
- if not self ._data . _real :
592
+ if self ._data is None :
588
593
# Create the data file. We do this at construction time so that the
589
594
# data file will be written into the directory where the process
590
595
# started rather than wherever the process eventually chdir'd to.
@@ -614,6 +619,9 @@ def start(self) -> None:
614
619
self ._init_for_start ()
615
620
self ._post_init ()
616
621
622
+ assert self ._collector is not None
623
+ assert self ._inorout is not None
624
+
617
625
# Issue warnings for possible problems.
618
626
self ._inorout .warn_conflicting_settings ()
619
627
@@ -635,6 +643,7 @@ def stop(self) -> None:
635
643
if self ._instances [- 1 ] is self :
636
644
self ._instances .pop ()
637
645
if self ._started :
646
+ assert self ._collector is not None
638
647
self ._collector .stop ()
639
648
self ._started = False
640
649
@@ -664,10 +673,12 @@ def erase(self) -> None:
664
673
"""
665
674
self ._init ()
666
675
self ._post_init ()
667
- self ._collector .reset ()
676
+ if self ._collector is not None :
677
+ self ._collector .reset ()
668
678
self ._init_data (suffix = None )
679
+ assert self ._data is not None
669
680
self ._data .erase (parallel = self .config .parallel )
670
- self ._data = _CoverageDataPlacebo ()
681
+ self ._data = None
671
682
self ._inited_for_start = False
672
683
673
684
def switch_context (self , new_context : str ) -> None :
@@ -686,6 +697,7 @@ def switch_context(self, new_context: str) -> None:
686
697
if not self ._started : # pragma: part started
687
698
raise CoverageException ("Cannot switch context, coverage is not started" )
688
699
700
+ assert self ._collector is not None
689
701
if self ._collector .should_start_context :
690
702
self ._warn ("Conflicting dynamic contexts" , slug = "dynamic-conflict" , once = True )
691
703
@@ -791,6 +803,7 @@ def combine(
791
803
self ._post_init ()
792
804
self .get_data ()
793
805
806
+ assert self ._data is not None
794
807
combine_parallel_data (
795
808
self ._data ,
796
809
aliases = self ._make_aliases (),
@@ -814,13 +827,15 @@ def get_data(self) -> CoverageData:
814
827
self ._init_data (suffix = None )
815
828
self ._post_init ()
816
829
817
- for plugin in self ._plugins :
818
- if not plugin ._coverage_enabled :
819
- self ._collector .plugin_was_disabled (plugin )
830
+ if self ._collector is not None :
831
+ for plugin in self ._plugins :
832
+ if not plugin ._coverage_enabled :
833
+ self ._collector .plugin_was_disabled (plugin )
820
834
821
- if self ._collector .flush_data ():
822
- self ._post_save_work ()
835
+ if self ._collector .flush_data ():
836
+ self ._post_save_work ()
823
837
838
+ assert self ._data is not None
824
839
return self ._data
825
840
826
841
def _post_save_work (self ) -> None :
@@ -830,6 +845,9 @@ def _post_save_work(self) -> None:
830
845
Look for un-executed files.
831
846
832
847
"""
848
+ assert self ._data is not None
849
+ assert self ._inorout is not None
850
+
833
851
# If there are still entries in the source_pkgs_unmatched list,
834
852
# then we never encountered those packages.
835
853
if self ._warn_unimported_source :
@@ -903,6 +921,7 @@ def _analyze(self, it: Union[FileReporter, TMorf]) -> Analysis:
903
921
904
922
def _get_file_reporter (self , morf : TMorf ) -> FileReporter :
905
923
"""Get a FileReporter for a module or file name."""
924
+ assert self ._data is not None
906
925
plugin = None
907
926
file_reporter : Union [str , FileReporter ] = "python"
908
927
@@ -938,6 +957,7 @@ def _get_file_reporters(self, morfs: Optional[Iterable[TMorf]] = None) -> List[F
938
957
measured is used to find the FileReporters.
939
958
940
959
"""
960
+ assert self ._data is not None
941
961
if not morfs :
942
962
morfs = self ._data .measured_files ()
943
963
@@ -952,7 +972,8 @@ def _prepare_data_for_reporting(self) -> None:
952
972
"""Re-map data before reporting, to get implicit 'combine' behavior."""
953
973
if self .config .paths :
954
974
mapped_data = CoverageData (warn = self ._warn , debug = self ._debug , no_disk = True )
955
- mapped_data .update (self ._data , aliases = self ._make_aliases ())
975
+ if self ._data is not None :
976
+ mapped_data .update (self ._data , aliases = self ._make_aliases ())
956
977
self ._data = mapped_data
957
978
958
979
def report (
@@ -1256,7 +1277,7 @@ def plugin_info(plugins: List[Any]) -> List[str]:
1256
1277
info = [
1257
1278
('coverage_version' , covmod .__version__ ),
1258
1279
('coverage_module' , covmod .__file__ ),
1259
- ('tracer' , self ._collector .tracer_name ()),
1280
+ ('tracer' , self ._collector .tracer_name () if self . _collector is not None else "-none-" ),
1260
1281
('CTracer' , 'available' if HAS_CTRACER else "unavailable" ),
1261
1282
('plugins.file_tracers' , plugin_info (self ._plugins .file_tracers )),
1262
1283
('plugins.configurers' , plugin_info (self ._plugins .configurers )),
@@ -1267,7 +1288,7 @@ def plugin_info(plugins: List[Any]) -> List[str]:
1267
1288
('config_contents' ,
1268
1289
repr (self .config ._config_contents ) if self .config ._config_contents else '-none-'
1269
1290
),
1270
- ('data_file' , self ._data .data_filename ()),
1291
+ ('data_file' , self ._data .data_filename () if self . _data is not None else "-none-" ),
1271
1292
('python' , sys .version .replace ('\n ' , '' )),
1272
1293
('platform' , platform .platform ()),
1273
1294
('implementation' , platform .python_implementation ()),
@@ -1288,44 +1309,14 @@ def plugin_info(plugins: List[Any]) -> List[str]:
1288
1309
('command_line' , " " .join (getattr (sys , 'argv' , ['-none-' ]))),
1289
1310
]
1290
1311
1291
- info .extend (self ._inorout .sys_info ())
1312
+ if self ._inorout is not None :
1313
+ info .extend (self ._inorout .sys_info ())
1314
+
1292
1315
info .extend (CoverageData .sys_info ())
1293
1316
1294
1317
return info
1295
1318
1296
1319
1297
- class _Placebo :
1298
- """Base class for placebos, to prevent calling the real base class __init__."""
1299
- def __init__ (self ) -> None :
1300
- ...
1301
-
1302
-
1303
- class _CoverageDataPlacebo (_Placebo , CoverageData ):
1304
- """Just enough of a CoverageData to be used when we don't have a real one."""
1305
- _real = False
1306
-
1307
- def data_filename (self ) -> str :
1308
- return "-none-"
1309
-
1310
-
1311
- class _CollectorPlacebo (_Placebo , Collector ):
1312
- """Just enough of a Collector to be used when we don't have a real one."""
1313
- def reset (self ) -> None :
1314
- ...
1315
-
1316
- def flush_data (self ) -> bool :
1317
- return False
1318
-
1319
- def tracer_name (self ) -> str :
1320
- return "-none-"
1321
-
1322
-
1323
- class _InOrOutPlacebo (_Placebo , InOrOut ):
1324
- """Just enough of an InOrOut to be used when we don't have a real one."""
1325
- def sys_info (self ) -> Iterable [Tuple [str , Any ]]:
1326
- return []
1327
-
1328
-
1329
1320
# Mega debugging...
1330
1321
# $set_env.py: COVERAGE_DEBUG_CALLS - Lots and lots of output about calls to Coverage.
1331
1322
if int (os .environ .get ("COVERAGE_DEBUG_CALLS" , 0 )): # pragma: debugging
0 commit comments