33import logging
44import os
55import shutil
6- from dataclasses import MISSING , dataclass , fields
6+ from collections .abc import Sequence
7+ from dataclasses import MISSING , asdict , dataclass , fields
78from functools import cached_property
89from pathlib import Path
910from subprocess import run
10- from typing import Any , Sequence
11+ from typing import Any
1112
1213import pathspec
1314from hatchling .builders .hooks .plugin .interface import BuildHookInterface
1415
15- logger = logging .getLogger (__name__ )
16+ log = logging .getLogger (__name__ )
17+ log_level = logging .getLevelName (os .getenv ("HATCH_BUILD_SCRIPTS_LOG_LEVEL" , "INFO" ))
18+ log .setLevel (log_level )
1619
1720
1821class BuildScriptsHook (BuildHookInterface ):
@@ -30,28 +33,34 @@ def initialize(
3033 for script in all_scripts :
3134 if script .clean_out_dir :
3235 out_dir = Path (self .root , script .out_dir )
33- logger . info (f"Cleaning { out_dir } " )
36+ log . debug (f"Cleaning { out_dir } " )
3437 shutil .rmtree (out_dir , ignore_errors = True )
3538 elif script .clean_artifacts :
3639 for out_file in script .out_files (self .root ):
40+ log .debug (f"Cleaning { out_file } " )
3741 out_file .unlink (missing_ok = True )
3842
3943 for script in all_scripts :
44+ log .debug (f"Script config: { asdict (script )} " )
4045 work_dir = Path (self .root , script .work_dir )
4146 out_dir = Path (self .root , script .out_dir )
4247 out_dir .mkdir (parents = True , exist_ok = True )
4348
4449 for cmd in script .commands :
50+ log .info (f"Running command: { cmd } " )
4551 run (cmd , cwd = str (work_dir ), check = True , shell = True ) # noqa: S602
4652
47- logger .info (f"Copying artifacts to { out_dir } " )
48- for artifact_file in script .artifact_files ():
49- src_file = work_dir / artifact_file
50- out_file = out_dir / artifact_file
53+ log .info (f"Copying artifacts to { out_dir } " )
54+ for work_file in script .work_files (self .root , relative = True ):
55+ src_file = work_dir / work_file
56+ out_file = out_dir / work_file
57+ log .debug (f"Copying { src_file } to { out_file } " )
5158 if src_file not in created :
5259 out_file .parent .mkdir (parents = True , exist_ok = True )
5360 shutil .copyfile (src_file , out_file )
5461 created .add (out_file )
62+ else :
63+ log .debug (f"Skipping { src_file } - already exists" )
5564
5665 build_data ["artifacts" ].append (str (out_dir .relative_to (self .root )))
5766
@@ -91,27 +100,32 @@ def __post_init__(self) -> None:
91100 self .out_dir = conv_path (self .out_dir )
92101 self .work_dir = conv_path (self .work_dir )
93102
94- def work_files (self , root : str | Path ) -> Sequence [Path ]:
95- """Get the files that will be used by the script ."""
96- work_dir = Path (root , self .work_dir )
97- if not work_dir .exists ():
103+ def work_files (self , root : str | Path , * , relative : bool = False ) -> Sequence [Path ]:
104+ """Get files in the work directory that match the artifacts spec ."""
105+ abs_dir = Path (root , self .work_dir )
106+ if not abs_dir .exists ():
98107 return []
99- return [Path (root , self .work_dir , f ) for f in self .artifacts_spec .match_tree (work_dir )]
100-
101- def out_files (self , root : str | Path ) -> Sequence [Path ]:
102- """Get the files that will be created by the script."""
103- out_dir = Path (root , self .out_dir )
104- if not out_dir .exists ():
108+ return [
109+ Path (f ) if relative else abs_dir / f
110+ for f in self .artifacts_spec .match_tree (abs_dir )
111+ ]
112+
113+ def out_files (self , root : str | Path , * , relative : bool = False ) -> Sequence [Path ]:
114+ """Get files in the output directory that match the artifacts spec."""
115+ abs_dir = Path (root , self .out_dir )
116+ if not abs_dir .exists ():
105117 return []
106- return [Path ( root , self . out_dir , f ) for f in self . artifacts_spec . match_tree ( out_dir )]
107-
108- def artifact_files ( self ) -> Sequence [ Path ]:
109- return [ Path ( conv_path ( p )) for p in self . artifacts_spec . match_tree ( self . work_dir ) ]
118+ return [
119+ Path ( f ) if relative else abs_dir / f
120+ for f in self . artifacts_spec . match_tree ( abs_dir )
121+ ]
110122
111123 @cached_property
112124 def artifacts_spec (self ) -> pathspec .PathSpec :
113125 """A pathspec for the artifacts."""
114- return pathspec .PathSpec .from_lines (pathspec .patterns .GitWildMatchPattern , self .artifacts )
126+ return pathspec .PathSpec .from_lines (
127+ pathspec .patterns .GitWildMatchPattern , self .artifacts
128+ )
115129
116130
117131def dataclass_defaults (obj : Any ) -> dict [str , Any ]:
0 commit comments