@@ -101,20 +101,17 @@ def get_current_branch() -> str:
101101 raise ValueError (f"Could not determine current branch: { stderr } " )
102102
103103
104- def get_mf6_ftypes (namefile_path : PathLike , ftypekeys : List [ str ] ) -> List [str ]:
104+ def get_packages (namefile_path : PathLike ) -> List [str ]:
105105 """
106- Return a list of FTYPES that are in the name file and in ftypekeys .
106+ Return a list of packages used by the model defined in the given namefile .
107107
108108 Parameters
109109 ----------
110- namefile_path : str
111- path to a MODFLOW 6 name file
112- ftypekeys : list
113- list of desired FTYPEs
110+ namefile_path : PathLike
111+ path to MODFLOW 6 name file
114112 Returns
115113 -------
116- ftypes : list
117- list of FTYPES that match ftypekeys in namefile
114+ list of package types
118115 """
119116 with open (namefile_path , "r" ) as f :
120117 lines = f .readlines ()
@@ -126,22 +123,29 @@ def get_mf6_ftypes(namefile_path: PathLike, ftypekeys: List[str]) -> List[str]:
126123 if len (ll ) < 2 :
127124 continue
128125
129- if ll [0 ] in ["#" , "!" ]:
126+ l = ll [0 ].lower ()
127+ if any (l .startswith (c ) for c in ["#" , "!" , "data" , "list" ]) or l in [
128+ "begin" ,
129+ "end" ,
130+ "memory_print_option" ,
131+ ]:
130132 continue
131133
132- for key in ftypekeys :
133- if key .lower () in ll [0 ].lower ():
134- ftypes .append (ll [0 ])
134+ # strip "6" from package name
135+ l = l .replace ("6" , "" )
135136
136- return ftypes
137+ ftypes . append ( l . lower ())
137138
139+ return list (set (ftypes ))
138140
139- def has_packages (namefile_path : PathLike , packages : List [str ]) -> bool :
140- ftypes = [item .upper () for item in get_mf6_ftypes (namefile_path , packages )]
141- return len (ftypes ) > 0
142141
142+ def has_package (namefile_path : PathLike , package : str ) -> bool :
143+ """Determines whether the model with the given namefile contains the selected package"""
144+ packages = get_packages (namefile_path )
145+ return package .lower in packages
143146
144- def get_models (
147+
148+ def get_model_paths (
145149 path : PathLike ,
146150 prefix : str = None ,
147151 namefile : str = "mfsim.nam" ,
@@ -150,7 +154,12 @@ def get_models(
150154 packages = None ,
151155) -> List [Path ]:
152156 """
153- Find models in the given filesystem location.
157+ Find models recursively in the given location.
158+ Models can be filtered or excluded by pattern,
159+ filtered by packages used or naming convention
160+ for namefiles, or by parent folder name prefix.
161+ The path to the model folder (i.e., the folder
162+ containing the model's namefile) is returned.
154163 """
155164
156165 # if path doesn't exist, return empty list
@@ -161,7 +170,7 @@ def get_models(
161170 namfile_paths = [
162171 p
163172 for p in Path (path ).rglob (
164- f"{ prefix } */{ namefile } " if prefix else namefile
173+ f"{ prefix } */**/ { namefile } " if prefix else namefile
165174 )
166175 ]
167176
@@ -172,37 +181,36 @@ def get_models(
172181 if (not excluded or not any (e in str (p ) for e in excluded ))
173182 ]
174183
175- # filter by package (optional)
184+ # filter by package
176185 if packages :
177- namfile_paths = [
178- p
179- for p in namfile_paths
180- if (has_packages (p , packages ) if packages else True )
181- ]
182-
183- # get model dir paths
186+ filtered = []
187+ for nfp in namfile_paths :
188+ nf_pkgs = get_packages (nfp )
189+ shared = set (nf_pkgs ).intersection (
190+ set ([p .lower () for p in packages ])
191+ )
192+ if any (shared ):
193+ filtered .append (nfp )
194+ namfile_paths = filtered
195+
196+ # get model folder paths
184197 model_paths = [p .parent for p in namfile_paths ]
185198
186- # filter by model name (optional)
199+ # filter by model name
187200 if selected :
188201 model_paths = [
189202 model
190203 for model in model_paths
191204 if any (s in model .name for s in selected )
192205 ]
193206
194- # exclude dev examples on master or release branches
195- branch = get_current_branch ()
196- if "master" in branch .lower () or "release" in branch .lower ():
197- model_paths = [
198- model for model in model_paths if "_dev" not in model .name .lower ()
199- ]
200-
201- return model_paths
207+ return sorted (model_paths )
202208
203209
204210def is_connected (hostname ):
205- """See https://stackoverflow.com/a/20913928/ to test hostname."""
211+ """
212+ Tests whether the given URL is accessible.
213+ See https://stackoverflow.com/a/20913928/."""
206214 try :
207215 host = socket .gethostbyname (hostname )
208216 s = socket .create_connection ((host , 80 ), 2 )
@@ -214,6 +222,8 @@ def is_connected(hostname):
214222
215223
216224def is_in_ci ():
225+ """Determines whether the current process is running GitHub Actions CI"""
226+
217227 # if running in GitHub Actions CI, "CI" variable always set to true
218228 # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
219229 return bool (environ .get ("CI" , None ))
@@ -222,7 +232,7 @@ def is_in_ci():
222232def is_github_rate_limited () -> Optional [bool ]:
223233 """
224234 Determines if a GitHub API rate limit is applied to the current IP.
225- Note that running this function will consume an API request!
235+ Running this function will consume an API request!
226236
227237 Returns
228238 -------
0 commit comments