1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15- import collections
15+ from enum import Enum
1616import itertools
1717import json
1818import os
2121import sys
2222import textwrap
2323import venv
24- from typing import Dict , List , Optional
24+ from typing import Dict , List , NamedTuple
2525
2626import importlib_metadata
2727
2828
29- EnvFile = collections .namedtuple ("EnvFile" , ["path" , "site_packages_path" ])
29+ class EnvPathType (Enum ):
30+ SITE_PACKAGES = 1
31+ DATA = 2
32+
33+
34+ class EnvFile (NamedTuple ):
35+ path : pathlib .Path
36+ env_path : pathlib .Path
37+ type_ : EnvPathType = EnvPathType .SITE_PACKAGES
3038
3139
3240def console_script (env_path : pathlib .Path , module : str , func : str ) -> str :
@@ -48,9 +56,9 @@ def path_starts_with(path: pathlib.Path, prefix: pathlib.Path) -> bool:
4856 return path .parts [: len (prefix .parts )] == prefix .parts
4957
5058
51- def get_site_packages_path (
59+ def get_env_path (
5260 workspace : str , path : pathlib .Path , imports : List [pathlib .Path ]
53- ) -> pathlib . Path :
61+ ) -> EnvFile :
5462 # Import prefixes start with the workspace name, which might be the local workspace.
5563 # We first normalize the given path so that it starts with its workspace name.
5664 if path .parts [0 ] == ".." :
@@ -62,20 +70,24 @@ def get_site_packages_path(
6270
6371 for imp in imports :
6472 if path_starts_with (wspath , imp ):
65- return wspath .relative_to (imp )
73+ return EnvFile (path , wspath .relative_to (imp ))
74+
75+ imp_data = imp .parent / "data"
76+ if path_starts_with (wspath , imp_data ):
77+ return EnvFile (path , wspath .relative_to (imp_data ), EnvPathType .DATA )
6678
6779 if not is_external :
6880 # If the input wasn't an external path and it didn't match any import prefixes,
6981 # just return it as given.
70- return path
82+ return EnvFile ( path , path )
7183
7284 # External file that didn't match imports. Include but warn.
7385 # We include it as relative to its workspace directory, so strip the first component
7486 # off wspath.
7587 include_path = wspath .relative_to (wspath .parts [0 ])
7688 print (f"Warning: [{ path } ] didn't match any imports. Including as [{ include_path } ]" )
7789
78- return include_path
90+ return EnvFile ( path , include_path )
7991
8092
8193def is_external (file_ : pathlib .Path ) -> bool :
@@ -123,27 +135,32 @@ def get_files(build_env_input: Dict) -> List[EnvFile]:
123135 paths = [input_path ]
124136
125137 for path in paths :
126- site_packages_path = get_site_packages_path (workspace , path , imports )
127- if site_packages_path != path or always_link :
128- files .append (EnvFile ( path , site_packages_path ) )
138+ env_file = get_env_path (workspace , path , imports )
139+ if env_file . env_path != path or always_link :
140+ files .append (env_file )
129141
130142 return files
131143
132144
133145def is_data_file (file : EnvFile ) -> bool :
134- return file .site_packages_path .parts [0 ].endswith (".data" )
146+ return (
147+ file .type_ == EnvPathType .DATA
148+ or file .env_path .parts [0 ].endswith (".data" )
149+ )
135150
136151
137152def install_data_file (env_path : pathlib .Path , file : EnvFile ) -> None :
138153 if (
139- len (file .site_packages_path .parts ) > 2
140- and file .site_packages_path .parts [1 ] == "scripts"
154+ len (file .env_path .parts ) > 2
155+ and file .env_path .parts [1 ] == "scripts"
141156 ):
142157 install_included_script (env_path , file .path )
158+ elif file .type_ == EnvPathType .DATA :
159+ install_site_file (env_path , file )
143160
144161
145162def install_site_file (site_packages_path : pathlib .Path , file : EnvFile ) -> None :
146- site_path = site_packages_path / file .site_packages_path
163+ site_path = site_packages_path / file .env_path
147164 if not site_path .exists ():
148165 site_path .parent .mkdir (parents = True , exist_ok = True )
149166 site_path .symlink_to (file .path .resolve ())
0 commit comments