99import configparser
1010import datetime
1111import os
12- import tarfile
1312import warnings
1413from pathlib import Path
1514from typing import Any , Dict , Generator , List , Type
3534
3635from ..shared .helpers import get_spec_format_for_item , labeled_format_parameter_set
3736from ..spec_version_checker .spec_version_checker import get_ref_spec_from_module
37+ from .fixture_output import FixtureOutput
3838
3939
4040def default_output_directory () -> str :
@@ -53,18 +53,6 @@ def default_html_report_file_path() -> str:
5353 return ".meta/report_fill.html"
5454
5555
56- def strip_output_tarball_suffix (output : Path ) -> Path :
57- """Strip the '.tar.gz' suffix from the output path."""
58- if str (output ).endswith (".tar.gz" ):
59- return output .with_suffix ("" ).with_suffix ("" )
60- return output
61-
62-
63- def is_output_stdout (output : Path ) -> bool :
64- """Return True if the fixture output is configured to be stdout."""
65- return strip_output_tarball_suffix (output ).name == "stdout"
66-
67-
6856def pytest_addoption (parser : pytest .Parser ):
6957 """Add command-line options to pytest."""
7058 evm_group = parser .getgroup ("evm" , "Arguments defining evm executable behavior" )
@@ -229,12 +217,14 @@ def pytest_configure(config):
229217 EnvironmentDefaults .gas_limit = config .getoption ("block_gas_limit" )
230218 if config .option .collectonly :
231219 return
220+
221+ # Initialize fixture output configuration
222+ config .fixture_output = FixtureOutput .from_config (config )
223+
232224 if not config .getoption ("disable_html" ) and config .getoption ("htmlpath" ) is None :
233225 # generate an html report by default, unless explicitly disabled
234- config .option .htmlpath = (
235- strip_output_tarball_suffix (config .getoption ("output" ))
236- / default_html_report_file_path ()
237- )
226+ config .option .htmlpath = config .fixture_output .directory / default_html_report_file_path ()
227+
238228 # Instantiate the transition tool here to check that the binary path/trace option is valid.
239229 # This ensures we only raise an error once, if appropriate, instead of for every test.
240230 t8n = TransitionTool .from_binary_path (
@@ -288,7 +278,7 @@ def pytest_report_teststatus(report, config: pytest.Config):
288278 ...x...
289279 ```
290280 """
291- if is_output_stdout ( config .getoption ( "output" )):
281+ if config .fixture_output . is_stdout : # type: ignore[attr-defined]
292282 return report .outcome , "" , report .outcome .upper ()
293283
294284
@@ -303,12 +293,12 @@ def pytest_terminal_summary(
303293 actually run the tests.
304294 """
305295 yield
306- if is_output_stdout ( config .getoption ( "output" )):
296+ if config .fixture_output . is_stdout : # type: ignore[attr-defined]
307297 return
308298 stats = terminalreporter .stats
309299 if "passed" in stats and stats ["passed" ]:
310300 # append / to indicate this is a directory
311- output_dir = str (strip_output_tarball_suffix ( config .getoption ( "output" ))) + "/"
301+ output_dir = str (config .fixture_output . directory ) + "/" # type: ignore[attr-defined]
312302 terminalreporter .write_sep (
313303 "=" ,
314304 (
@@ -505,45 +495,33 @@ def base_dump_dir(request: pytest.FixtureRequest) -> Path | None:
505495
506496
507497@pytest .fixture (scope = "session" )
508- def is_output_tarball (request : pytest .FixtureRequest ) -> bool :
509- """Return True if the output directory is a tarball."""
510- output : Path = request .config .getoption ("output" )
511- if output .suffix == ".gz" and output .with_suffix ("" ).suffix == ".tar" :
512- return True
513- return False
498+ def fixture_output (request : pytest .FixtureRequest ) -> FixtureOutput :
499+ """Return the fixture output configuration."""
500+ return request .config .fixture_output # type: ignore[attr-defined]
514501
515502
516503@pytest .fixture (scope = "session" )
517- def output_dir (request : pytest .FixtureRequest , is_output_tarball : bool ) -> Path :
518- """Return directory to store the generated test fixtures."""
519- output = request .config .getoption ("output" )
520- if is_output_tarball :
521- return strip_output_tarball_suffix (output )
522- return output
504+ def is_output_tarball (fixture_output : FixtureOutput ) -> bool :
505+ """Return True if the output directory is a tarball."""
506+ return fixture_output .is_tarball
523507
524508
525509@pytest .fixture (scope = "session" )
526- def output_metadata_dir (output_dir : Path ) -> Path :
527- """Return metadata directory to store fixture meta files."""
528- if is_output_stdout (output_dir ):
529- return output_dir
530- return output_dir / ".meta"
510+ def output_dir (fixture_output : FixtureOutput ) -> Path :
511+ """Return directory to store the generated test fixtures."""
512+ return fixture_output .directory
531513
532514
533515@pytest .fixture (scope = "session" , autouse = True )
534- def create_properties_file (
535- request : pytest .FixtureRequest , output_dir : Path , output_metadata_dir : Path
536- ) -> None :
516+ def create_properties_file (request : pytest .FixtureRequest , fixture_output : FixtureOutput ) -> None :
537517 """
538518 Create ini file with fixture build properties in the fixture output
539519 directory.
540520 """
541- if is_output_stdout ( request . config . getoption ( "output" )) :
521+ if fixture_output . is_stdout :
542522 return
543- if not output_dir .exists ():
544- output_dir .mkdir (parents = True )
545- if not output_metadata_dir .exists ():
546- output_metadata_dir .mkdir (parents = True )
523+
524+ fixture_output .create_directories ()
547525
548526 fixture_properties = {
549527 "timestamp" : datetime .datetime .now ().isoformat (),
@@ -574,7 +552,7 @@ def create_properties_file(
574552 )
575553 config ["environment" ] = environment_properties
576554
577- ini_filename = output_metadata_dir / "fixtures.ini"
555+ ini_filename = fixture_output . metadata_dir / "fixtures.ini"
578556 with open (ini_filename , "w" ) as f :
579557 f .write ("; This file describes fixture build properties\n \n " )
580558 config .write (f )
@@ -610,9 +588,9 @@ def get_fixture_collection_scope(fixture_name, config):
610588
611589 See: https://docs.pytest.org/en/stable/how-to/fixtures.html#dynamic-scope
612590 """
613- if is_output_stdout ( config .getoption ( "output" )) :
591+ if config .fixture_output . is_stdout :
614592 return "session"
615- if config .getoption ( " single_fixture_per_file" ) :
593+ if config .fixture_output . single_fixture_per_file :
616594 return "function"
617595 return "module"
618596
@@ -636,17 +614,17 @@ def fixture_collector(
636614 evm_fixture_verification : FixtureConsumer ,
637615 filler_path : Path ,
638616 base_dump_dir : Path | None ,
639- output_dir : Path ,
617+ fixture_output : FixtureOutput ,
640618) -> Generator [FixtureCollector , None , None ]:
641619 """
642620 Return configured fixture collector instance used for all tests
643621 in one test module.
644622 """
645623 fixture_collector = FixtureCollector (
646- output_dir = output_dir ,
647- flat_output = request . config . getoption ( " flat_output" ) ,
624+ output_dir = fixture_output . directory ,
625+ flat_output = fixture_output . flat_output ,
648626 fill_static_tests = request .config .getoption ("fill_static_tests_enabled" ),
649- single_fixture_per_file = request . config . getoption ( " single_fixture_per_file" ) ,
627+ single_fixture_per_file = fixture_output . single_fixture_per_file ,
650628 filler_path = filler_path ,
651629 base_dump_dir = base_dump_dir ,
652630 )
@@ -875,29 +853,20 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
875853 if xdist .is_xdist_worker (session ):
876854 return
877855
878- output : Path = session .config .getoption ( "output" )
856+ fixture_output = session .config .fixture_output # type: ignore[attr-defined]
879857 # When using --collect-only it should not matter whether fixtures folder exists or not
880- if is_output_stdout ( output ) or session .config .option .collectonly :
858+ if fixture_output . is_stdout or session .config .option .collectonly :
881859 return
882860
883- output_dir = strip_output_tarball_suffix (output )
884861 # Remove any lock files that may have been created.
885- for file in output_dir .rglob ("*.lock" ):
862+ for file in fixture_output . directory .rglob ("*.lock" ):
886863 file .unlink ()
887864
888865 # Generate index file for all produced fixtures.
889866 if session .config .getoption ("generate_index" ):
890867 generate_fixtures_index (
891- output_dir , quiet_mode = True , force_flag = False , disable_infer_format = False
868+ fixture_output . directory , quiet_mode = True , force_flag = False , disable_infer_format = False
892869 )
893870
894871 # Create tarball of the output directory if the output is a tarball.
895- is_output_tarball = output .suffix == ".gz" and output .with_suffix ("" ).suffix == ".tar"
896- if is_output_tarball :
897- source_dir = output_dir
898- tarball_filename = output
899- with tarfile .open (tarball_filename , "w:gz" ) as tar :
900- for file in source_dir .rglob ("*" ):
901- if file .suffix in {".json" , ".ini" }:
902- arcname = Path ("fixtures" ) / file .relative_to (source_dir )
903- tar .add (file , arcname = arcname )
872+ fixture_output .create_tarball ()
0 commit comments