Skip to content

Commit

Permalink
Add library search option using glob
Browse files Browse the repository at this point in the history
  • Loading branch information
langmm committed May 21, 2024
1 parent 55d147f commit 43b8448
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 71 deletions.
45 changes: 22 additions & 23 deletions yggdrasil/drivers/CompiledModelDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3635,33 +3635,32 @@ def _search_brute(self, fname, libtype=None, verbose=False,
fname_ext = expected_ext[0]
if os.path.isfile(fname):
return fname
use_regex = (not platform._is_win)
if use_regex:
fname = (
r'[^a-zA-Z]'
+ tools.escape_regex(fname_base)
+ r'\([^a-zA-Z].*\)?'
+ tools.escape_regex(fname_ext))
else:
fname = fname_base + '*' + fname_ext
use_regex = True # (not platform._is_win)
fname_try = [fname_base]
if platform._is_win and libtype in self.library_files:
if fname_base.startswith('lib'):
fname_try.append(fname_base[3:])
else:
fname_try.append('lib' + fname_try)
search_list = self.tool(libtype).get_search_path(
libtype=libtype, cfg=self.cfg, **kwargs)
out = tools.locate_file(fname, directory_list=search_list,
environment_variable=None,
use_regex=use_regex)
if (not out) and use_regex:
fname = fname_base + '*' + fname_ext
for fname_base in fname_try:
use_glob = fname_base + '*' + fname_ext
if use_regex:
fname = (
r'[^a-zA-Z]'
+ tools.escape_regex(fname_base)
+ r'([^a-zA-Z].*)?'
+ tools.escape_regex(fname_ext))
else:
fname = use_glob
out = tools.locate_file(fname, directory_list=search_list,
environment_variable=None,
use_regex=False)
if (((not out) and platform._is_win
and libtype in self.library_files)):
if fname.startswith('lib'):
alt = fname[3:]
else:
alt = 'lib' + fname
out = tools.locate_file(alt, directory_list=search_list,
environment_variable=None)
use_regex=use_regex,
use_glob=use_glob,
select_return='shortest')
if out:
break
if ((out and not dont_check_windows_import
and libtype in ['static', 'windows_import']
and platform._is_win)): # pragma: windows
Expand Down
146 changes: 98 additions & 48 deletions yggdrasil/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,24 @@ def escape_regex(name):
return out


def find_all(name, path, verification_func=None, use_regex=False):
def convert_regex_to_find(name):
r"""Convert a regex pattern for fortran to the format expected by the
linux find command.
Args:
name (str): Pattern to convert.
Returns:
str: Converted pattern,
"""
out = re.sub(r'(^|(?:[^\\]))\(', r'\1\(', name)
out = re.sub(r'(^|(?:[^\\]))\)', r'\1\)', out)
return out


def find_all(name, path, verification_func=None, use_regex=False,
use_glob=False):
r"""Find all instances of a file with a given name within the directory
tree starting at a given path.
Expand All @@ -616,54 +633,70 @@ def find_all(name, path, verification_func=None, use_regex=False):
otherwise. Defaults to None and is ignored.
use_regex (bool, optional): If True, use full regex to interpret
name and locate files.
use_glob (bool, str, optional): If True or string, use glob
to locate the file. If use_regex is True, a string must be
provided containing the glob search expression.
Returns:
list: All instances of the specified file.
"""
result = []
args = []
try:
if platform._is_win: # pragma: windows
assert not use_regex
args = ["where"]
if path is None:
args += [name]
out = subprocess.check_output(args,
env=os.environ,
stderr=subprocess.STDOUT)
else:
args += ["/r", path, name]
out = subprocess.check_output(args,
env=os.environ,
stderr=subprocess.STDOUT)
else:
shell = False
args = ["find", "-L", path, "-type", "f"]
if use_regex:
args += ["-regex", r'.*' + name]
args.insert(1, "-E")
args = ' '.join(args)
shell = True
if use_glob:
fglob = os.path.join(path, name)
if use_regex:
assert isinstance(use_glob, str)
fglob = os.path.join(path, use_glob)
result = glob.glob(fglob)
if use_regex:
result = [
x for x in result
if re.fullmatch(r'.*' + name, x)]
else:
try:
if platform._is_win: # pragma: windows
assert not use_regex
args = ["where"]
if path is None:
args += [name]
out = subprocess.check_output(
args, env=os.environ,
stderr=subprocess.STDOUT)
else:
args += ["/r", path, name]
out = subprocess.check_output(
args, env=os.environ,
stderr=subprocess.STDOUT)
else:
args += ["-name", name]
pfind = subprocess.Popen(args, env=os.environ, shell=shell,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
if isinstance(args, list):
args = ' '.join(args)
(stdoutdata, stderrdata) = pfind.communicate()
out = stdoutdata
for line in stderrdata.splitlines():
if b'Permission denied' not in line:
raise subprocess.CalledProcessError(pfind.returncode,
args,
output=stderrdata)
except subprocess.CalledProcessError as e:
logger.info(f"Error in called process \'{args}\': {e}")
out = ''
if not out.isspace():
result = sorted(out.splitlines())
shell = False
args = ["find", "-L", path, "-type", "f"]
if use_regex:
name = convert_regex_to_find(name)
args += ["-regex", r'.*' + name]
args.insert(1, "-E")
args = ' '.join(args)
shell = True
else:
args += ["-name", name]
pfind = subprocess.Popen(
args, env=os.environ, shell=shell,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
if isinstance(args, list):
args = ' '.join(args)
(stdoutdata, stderrdata) = pfind.communicate()
out = stdoutdata
for line in stderrdata.splitlines():
if b'Permission denied' not in line:
raise subprocess.CalledProcessError(
pfind.returncode, args,
output=stderrdata)
except subprocess.CalledProcessError as e:
logger.info(f"Error in called process \'{args}\': {e}")
out = ''
if not out.isspace():
result = sorted(out.splitlines())
result = [os.path.normcase(os.path.normpath(bytes2str(m)))
for m in result]
if verification_func is not None:
Expand All @@ -672,7 +705,7 @@ def find_all(name, path, verification_func=None, use_regex=False):


def locate_file(fname, environment_variable='PATH', directory_list=None,
show_alternates=False, **kwargs):
show_alternates=False, select_return='first', **kwargs):
r"""Locate a file within a set of paths defined by a list or environment
variable.
Expand All @@ -693,6 +726,12 @@ def locate_file(fname, environment_variable='PATH', directory_list=None,
show_alternates (bool, optional): If True and there is more
than one match, the alternate matches will be printed in
a warning message. Defaults to False.
select_return (str, optional): Method that should be used to select
the returned value if there is more than one option.
'first' : Return the first value, alphabetically sorted.
'last' : Return the last value, alphabetically sorted.
'longest' : Return the longest value.
'shortest': Return the shortest value.
**kwargs: Additional keyword arguments are passed to find_all.
Returns:
Expand All @@ -705,13 +744,15 @@ def locate_file(fname, environment_variable='PATH', directory_list=None,
for ifname in fname:
out = locate_file(ifname, environment_variable=environment_variable,
directory_list=directory_list,
show_alternates=show_alternates, **kwargs)
show_alternates=show_alternates,
select_return=select_return, **kwargs)
if out:
break
return out
out = []
if ((platform._is_win and (environment_variable == 'PATH')
and (directory_list is None))): # pragma: windows
and (directory_list is None)
and not kwargs.get('use_glob', False))): # pragma: windows
out += find_all(fname, None, **kwargs)
else:
if directory_list is None:
Expand All @@ -728,15 +769,24 @@ def locate_file(fname, environment_variable='PATH', directory_list=None,
break
if not out:
return False
if len(out) > 1:
if select_return in ['first', 'last']:
out = sorted(out)
elif select_return in ['longest', 'shortest']:
out = sorted(out, key=len)
else: # pragma: debug
raise NotImplementedError(select_return)
if select_return in ['last', 'longest']:
out = out[::-1]
first = out[0]
if show_alternates: # pragma: debug
out = set(out)
out.remove(first)
if len(out) > 0:
warnings.warn(("More than one (%d) match to %s:\n%s\n "
+ "Using first match (%s)") %
(len(out) + 1, fname, pprint.pformat(out),
first), RuntimeWarning)
warnings.warn(
f"More than one ({len(out) + 1}) match to {fname}:\n"
f"{pprint.pformat(out)}\n "
f"Using {select_return} match ({first})", RuntimeWarning)
return first


Expand Down

0 comments on commit 43b8448

Please sign in to comment.