Skip to content
Merged
2 changes: 1 addition & 1 deletion .github/workflows/push-pull.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
do-codecov: true
do-codacy: false
do-coveralls: false
do-ruff-check: false
do-ruff-check: true
14 changes: 5 additions & 9 deletions pyiron_snippets/deprecate.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,28 +108,26 @@ def __call__(self, message=None, version=None, arguments=None, **kwargs):
return depr.wrap

def _build_message(self):
if self.category == PendingDeprecationWarning:
if self.category is PendingDeprecationWarning:
message_format = "{} will be deprecated"
else:
message_format = "{} is deprecated"

if self.message is not None:
message_format += ": {}.".format(self.message)
message_format += f": {self.message}."
else:
message_format += "."

if self.version is not None:
message_format += (
" It is not guaranteed to be in service in vers. {}".format(
self.version
)
f" It is not guaranteed to be in service in vers. {self.version}"
)

return message_format

def __deprecate_function(self, function):
message = self._build_message().format(
"{}.{}".format(function.__module__, function.__name__)
f"{function.__module__}.{function.__name__}"
)

@functools.wraps(function)
Expand All @@ -148,9 +146,7 @@ def decorated(*args, **kwargs):
if kw in self.arguments:
warnings.warn(
message_format.format(
"{}.{}({}={})".format(
function.__module__, function.__name__, kw, kwargs[kw]
)
"{function.__module__}.{function.__name__}({kw}={kwargs[kw]})"
),
category=self.category,
stacklevel=2,
Expand Down
2 changes: 1 addition & 1 deletion pyiron_snippets/dotdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def __getattr__(self, item):
except KeyError:
raise AttributeError(
f"{self.__class__.__name__} object has no attribute '{item}'"
)
) from None

def __setattr__(self, key, value):
self[key] = value
Expand Down
16 changes: 8 additions & 8 deletions pyiron_snippets/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ class creation via :func:`builtins.type` -- i.e. taking a class name, a tuple of

from __future__ import annotations

import pickle
from abc import ABC, ABCMeta
from abc import ABCMeta
from functools import wraps
from importlib import import_module
from inspect import Parameter, signature
Expand All @@ -48,7 +47,7 @@ class _SingleInstance(ABCMeta):

def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(_SingleInstance, cls).__call__(*args, **kwargs)
cls._instance = super().__call__(*args, **kwargs)
return cls._instance


Expand Down Expand Up @@ -181,19 +180,19 @@ def clear(cls, *class_names, skip_missing=True):
for name in class_names:
try:
cls.class_registry.pop(name)
except KeyError as e:
except KeyError:
if skip_missing:
continue
else:
raise KeyError(f"Could not find class {name}")
raise KeyError(f"Could not find class {name}") from None

def _build_class(
self, name, bases, class_dict, sc_init_kwargs, class_factory_args
) -> type[_FactoryMade]:

if "__module__" not in class_dict.keys():
if "__module__" not in class_dict:
class_dict["__module__"] = self.factory_function.__module__
if "__qualname__" not in class_dict.keys():
if "__qualname__" not in class_dict:
class_dict["__qualname__"] = f"{self.__qualname__}.{name}"
sc_init_kwargs["class_factory"] = self
sc_init_kwargs["class_factory_args"] = class_factory_args
Expand Down Expand Up @@ -233,7 +232,7 @@ def _import_object(module_name, qualname):
return obj


class _FactoryMade(ABC):
class _FactoryMade:
"""
A mix-in to make class-factory-produced classes pickleable.

Expand Down Expand Up @@ -386,6 +385,7 @@ def classfactory(
>>> import pickle
>>>
>>> from pyiron_snippets.factory import classfactory
>>> from abc import ABC
>>>
>>> class HasN(ABC):
... '''Some class I want to make dynamically subclass.'''
Expand Down
11 changes: 4 additions & 7 deletions pyiron_snippets/import_alarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def warn_if_failed(self):
trigger the warning.
"""
if self.message is not None:
warnings.warn(self.message, category=ImportWarning)
warnings.warn(self.message, category=ImportWarning, stacklevel=2)
if self._fail_on_warning:
raise ImportAlarmError(self.message)

Expand All @@ -89,9 +89,6 @@ def __exit__(self, exc_type, exc_value, traceback):
# import successful, so silence our warning
self.message = None
return
if issubclass(exc_type, ImportError):
# import broken; retain message, but suppress error
return True
else:
# unrelated error during import, re-raise
return False
# True: import broken; retain message, but suppress error
# False: unrelated error during import, re-raise
return issubclass(exc_type, ImportError)
7 changes: 2 additions & 5 deletions pyiron_snippets/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
from glob import glob
from typing import Any

if os.name == "nt":
EXE_SUFFIX = "bat"
else:
EXE_SUFFIX = "sh"
EXE_SUFFIX = "bat" if os.name == "nt" else "sh"


class ResourceNotFound(RuntimeError):
Expand Down Expand Up @@ -89,7 +86,7 @@ def first(self, name: Iterable[str] | str = "*") -> Any:
except StopIteration:
raise ResourceNotFound(f"Could not find {name} in {self}!") from None

def chain(self, *resolvers: "AbstractResolver") -> "ResolverChain":
def chain(self, *resolvers: AbstractResolver) -> ResolverChain:
"""
Return a new resolver that searches this and all given resolvers sequentially.

Expand Down
14 changes: 6 additions & 8 deletions pyiron_snippets/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

import time
import warnings
from collections.abc import Callable
from itertools import count
from typing import Callable, Optional, Tuple, Type, TypeVar, Union
from typing import TypeVar

T = TypeVar("T")


def retry(
func: Callable[[], T],
error: Union[Type[Exception], Tuple[Type[Exception], ...]],
error: type[Exception] | tuple[type[Exception], ...],
msg: str,
at_most: Optional[int] = None,
at_most: int | None = None,
delay: float = 1.0,
delay_factor: float = 1.0,
log: bool | object = True,
Expand Down Expand Up @@ -42,18 +43,15 @@ def retry(
Returns:
object: whatever is returned by `func`
"""
if at_most is None:
tries = count()
else:
tries = range(at_most)
tries = count() if at_most is None else range(at_most)
for i in tries:
try:
return func()
except error as e:
warning = f"{msg} Trying again in {delay}s. Tried {i + 1} times so far..."
if isinstance(log, bool):
if log:
warnings.warn(warning)
warnings.warn(warning, stacklevel=2)
else:
log.warn(warning)
time.sleep(delay)
Expand Down
2 changes: 1 addition & 1 deletion pyiron_snippets/singleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ class Singleton(ABCMeta):

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
6 changes: 2 additions & 4 deletions pyiron_snippets/tempenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@ def TemporaryEnvironment(**kwargs):
"""
old_vars = {}
for k, v in kwargs.items():
try:
with contextlib.suppress(KeyError):
old_vars[k] = os.environ[k]
except KeyError:
pass
os.environ[k] = str(v)
try:
yield
finally:
for k, v in kwargs.items():
for k in kwargs:
if k in old_vars:
os.environ[k] = old_vars[k]
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def load_tests(loader, tests, ignore):
for importer, name, ispkg in pkgutil.walk_packages(
for _, name, _ in pkgutil.walk_packages(
pyiron_snippets.__path__, pyiron_snippets.__name__ + "."
):
tests.addTests(doctest.DocTestSuite(name))
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_dotdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_dot_dict(self):
with self.assertRaises(
AttributeError, msg="Failed attribute access should raise attribute error"
):
dd.missing
_ = dd.missing


if __name__ == "__main__":
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)


class HasN(ABC):
class HasN:
def __init_subclass__(cls, /, n=0, s="foo", **kwargs):
super().__init_subclass__(**kwargs)
cls.n = n
Expand Down Expand Up @@ -53,7 +53,7 @@ def has_n_factory(n, s="decorated_method", /):
Has2 = has_n_factory(2, "factory_made") # For testing repeated inheritance


class HasM(ABC):
class HasM:
def __init_subclass__(cls, /, m=0, **kwargs):
super(HasM, cls).__init_subclass__(**kwargs)
cls.m = m
Expand Down Expand Up @@ -163,7 +163,7 @@ def test_factory_initialization(self):
factory = has_n_factory(2, "foo")
self.assertTrue(
issubclass(factory, HasN),
msg=f"Resulting class should inherit from the base",
msg="Resulting class should inherit from the base",
)
self.assertEqual(2, factory.n, msg="Factory args should get interpreted")
self.assertEqual("foo", factory.s, msg="Factory kwargs should get interpreted")
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ def test_copy(self):
new_file_1 = f.copy("another_test")
self.assertEqual(new_file_1.read(), "sam wrote this wondrful thing")
new_file_2 = f.copy("another_test", ".")
with open("another_test", "r") as file:
with open("another_test") as file:
txt = file.read()
self.assertEqual(txt, "sam wrote this wondrful thing")
new_file_2.delete() # needed because current directory
new_file_3 = f.copy(str(f.path.parent / "another_test"), ".")
self.assertEqual(new_file_1.path.absolute(), new_file_3.path.absolute())
new_file_4 = f.copy(directory=".")
with open("test_copy.txt", "r") as file:
with open("test_copy.txt") as file:
txt = file.read()
self.assertEqual(txt, "sam wrote this wondrful thing")
new_file_4.delete() # needed because current directory
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_tempenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_raise_exception(self):
with TemporaryEnvironment(FOO="1"):
self.assertEqual(os.environ.get("FOO"), "1")
raise Exception("Some Error")
except:
except Exception:
self.assertEqual(
os.environ.get("FOO"),
"0",
Expand Down
Loading