Skip to content

Commit

Permalink
Merge pull request #22 from pyiron/warn
Browse files Browse the repository at this point in the history
Log a warning when an executable is found, but does not have the exec…
  • Loading branch information
pmrv authored Jul 24, 2024
2 parents 4d26756 + efd976c commit 0089e58
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
17 changes: 17 additions & 0 deletions pyiron_snippets/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from glob import glob
import re
from typing import Any
import warnings

if os.name == "nt":
EXE_SUFFIX = "bat"
Expand All @@ -23,6 +24,10 @@ class ResourceNotFound(RuntimeError):
pass


class ResolverWarning(RuntimeWarning):
pass


class AbstractResolver(ABC):
"""
Interface for resolvers.
Expand Down Expand Up @@ -204,6 +209,9 @@ class ExecutableResolver(AbstractResolver):
and have the executable bit set. :meth:`.search` yields tuples of version strings and full paths to the executable
instead of plain strings.
Except on windows results are filtered to make sure all returned scripts have the executable bit set.
When the bit is not set, a warning is printed.
>>> exe = ExecutableResolver(..., "lammps")
>>> exe.list() # doctest: +SKIP
[
Expand Down Expand Up @@ -255,9 +263,18 @@ def _search(self, name):

def cond(path):
isfile = os.path.isfile(path)
# HINT: this is always True on windows
isexec = os.access(
path, os.X_OK, effective_ids=os.access in os.supports_effective_ids
)
if isfile and not isexec:
warnings.warn(
f"Found file '{path}', but skipping it because it is not executable!",
category=ResolverWarning,
# TODO: maybe used from python3.12 onwards
# skip_file_prefixes=(os.path.dirname(__file__),),
stacklevel=4,
)
return isfile and isexec

for path in filter(cond, self._resolver.search(self._glob)):
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/test_resources.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import os.path
import unittest
from pyiron_snippets.resources import ResourceNotFound, ResourceResolver, ExecutableResolver
from pyiron_snippets.resources import ResourceNotFound, ResourceResolver, ExecutableResolver, ResolverWarning

class TestResolvers(unittest.TestCase):
"""
Expand Down Expand Up @@ -55,8 +55,10 @@ def test_executable(self):
for suffix in (None, "sh", "bat"):
with self.subTest(suffix=suffix):
res = ExecutableResolver([self.res1], code="code1", module="module1", suffix=suffix)
# Windows always reports the exec bit as set, so skip those tests there
if os.name != "nt":
# no exec bits are present on windows it seems
with self.assertWarns(ResolverWarning):
res.list()
self.assertNotIn("versionnonexec", res.available_versions,
"ExecutableResolver must not list scripts that are not executable.")
self.assertNotIn("wrong_format", res.available_versions,
Expand Down

0 comments on commit 0089e58

Please sign in to comment.