Skip to content

Commit 9426779

Browse files
committed
Merge branch '988-fix'
2 parents 509d599 + 53b9b52 commit 9426779

File tree

2 files changed

+73
-21
lines changed

2 files changed

+73
-21
lines changed

changes/988.fix.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed sile exploration with specification
2+
3+
E.g. `sgeom test{car}` has to be changed to
4+
`sgeom test{startswith=car}` to get a singular
5+
sile match.

src/sisl/io/sile.py

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def __init__(self, cls, suffix, case=True, gzip=False):
8888
self.base_names = [c.__name__.lower() for c in self.bases]
8989

9090
def __str__(self):
91-
s = ",\n ".join(map(lambda x: x.__name, self.bases))
91+
s = ",\n ".join(map(lambda x: x.__name__, self.bases))
9292
return (
9393
f"{self.cls.__name__}{{case={self.case}, "
9494
f"suffix={self.suffix}, gzip={self.gzip},\n {s}\n}}"
@@ -244,8 +244,7 @@ def get_sile_class(filename, *args, **kwargs):
244244
if specification is None:
245245
# ensure to grab nothing
246246
specification = get_environ_variable("SISL_IO_DEFAULT").strip()
247-
elif specification.strip() == "":
248-
specification = ""
247+
specification = specification.strip()
249248

250249
# extract which comparsion method
251250
if "=" in specification:
@@ -277,15 +276,30 @@ def get_sile_class(filename, *args, **kwargs):
277276
f"Specification requirement of the file did not result in any found files: {specification}"
278277
)
279278

280-
else:
281-
# search everything
282-
eligible_rules = __sile_rules
279+
def reduce_rules(rules):
280+
# Reduce so we are stuck with only non-equivalent ones
281+
i = 0
282+
n = 0
283+
while n != len(rules) and i < len(rules):
284+
n = len(rules)
285+
# Search for classes equivalent to idx i
286+
rule = rules[i]
287+
pop_idx = []
288+
for j in range(i + 1, n):
289+
if rule.is_class(rules[j].cls):
290+
pop_idx.append(j)
291+
292+
# Remove equivalent ones
293+
for j in reversed(pop_idx):
294+
rules.pop(j)
295+
# Check the next i
296+
i += 1
283297

284298
if eligible_rules:
285299
if len(eligible_rules) == 1:
286300
return eligible_rules[0].cls
287301
else:
288-
# nothing has been found, this may meen that we need to search *everything*
302+
# nothing has been found, this may mean that we need to search *everything*
289303
eligible_rules = __sile_rules
290304

291305
try:
@@ -355,27 +369,60 @@ def get_eligibles(end, rules):
355369
eligibles.append(sr)
356370
return eligibles
357371

358-
# First we check for class AND file ending
359-
for end, rules in product(end_list, (eligible_rules, __sile_rules)):
360-
eligibles = get_eligibles(end, rules)
361-
# Determine whether we have found a compatible sile
362-
if len(eligibles) == 1:
363-
return eligibles[0].cls
364-
elif len(eligibles) > 1:
365-
workable_eligibles = try_methods(eligibles)
366-
if len(workable_eligibles) == 1:
367-
return workable_eligibles[0].cls
368-
raise ValueError(
369-
f"Cannot determine the exact Sile requested, multiple hits: {tuple(e.cls.__name__ for e in eligibles)}"
370-
)
372+
def run_eligibles(end_list, rules) -> Optional[_sile_rule]:
373+
# First we check for class AND file ending
374+
for end in end_list:
375+
eligibles = get_eligibles(end, rules)
376+
# Determine whether we have found a compatible sile
377+
if len(eligibles) == 1:
378+
return eligibles[0]
379+
elif len(eligibles) > 1:
380+
workable_eligibles = try_methods(eligibles)
381+
if len(workable_eligibles) == 1:
382+
return workable_eligibles[0]
383+
raise ValueError(
384+
f"Cannot determine the exact Sile requested, multiple hits: {tuple(e.cls.__name__ for e in eligibles)}"
385+
)
386+
387+
# First check for the user-requested rules
388+
# Specific is same object check!
389+
if eligible_rules and not (eligible_rules is __sile_rules):
390+
# This will test the file-endings for all found eligible_rules
391+
# So file-endings are still preferred up to this point.
392+
rule = run_eligibles(end_list, eligible_rules)
393+
394+
if rule is not None:
395+
return rule.cls
396+
397+
# We did not find a single one, so file-endings could not produce
398+
# a match in the eligible ones.
399+
# Reduce and see if they are all the same.
400+
reduce_rules(eligible_rules)
401+
if len(eligible_rules) == 1:
402+
return eligible_rules[0].cls
403+
404+
# At this point, we issues a warning saying that the
405+
# the rules requested could not find a match
406+
eligibles = list(map(lambda x: x.cls.__name__, eligible_rules))
407+
warn(
408+
"Specification requirement of the file resulted in too many "
409+
f"matches: {eligibles}"
410+
)
411+
412+
rule = run_eligibles(end_list, __sile_rules)
413+
414+
if rule is not None:
415+
return rule.cls
371416

372417
# Print-out error on which extensions it tried (and full filename)
373418
if len(end_list) == 1:
374419
ext_list = end_list
375420
else:
376421
ext_list = end_list[1:]
422+
# Retrieve the possible extensions searched
423+
eligibles = list(map(lambda x: x.cls.__name__, eligible_rules))
377424
raise NotImplementedError(
378-
f"Sile for file '{filename}' ({ext_list}) could not be found, "
425+
f"Sile for file '{filename}' ({ext_list}, {eligibles}) could not be found, "
379426
"possibly the file has not been implemented."
380427
)
381428

0 commit comments

Comments
 (0)