Skip to content

Commit

Permalink
Merge pull request #50 from ubermag/precommit_updates
Browse files Browse the repository at this point in the history
Update pre-commits and pytest configuration
  • Loading branch information
samjrholt authored Jun 4, 2024
2 parents 2a8aff1 + 0fbe4d8 commit 63ca281
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 130 deletions.
36 changes: 11 additions & 25 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
default_language_version:
python: python3.8
exclude: 'dev'

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-merge-conflict # checks for files that contain merge conflict strings
- id: check-toml # checks toml files for parseable syntax
- id: debug-statements # checks for debugger imports and py37+ `breakpoint()` calls in python source
# - id: trailing-whitespace # needs more checks
# args: [--markdown-linebreak-ext=md]
# exclude: 'ubermagutil/tests/test_sample/.*'

- repo: https://github.com/pycqa/isort
rev: 5.12.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: isort

- repo: https://github.com/nbQA-dev/nbQA
rev: 1.6.3
hooks:
- id: nbqa-isort # isort inside Jupyter notebooks

- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies: [flake8-rst-docstrings] #, flake8-docstrings]

- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black-jupyter
# Run the linter.
- id: ruff
types_or: [python, pyi, jupyter]
args: [--fix, --exit-non-zero-on-fix]
# Run the formatter.
- id: ruff-format
types_or: [python, pyi, jupyter]

# - repo: https://github.com/codespell-project/codespell
# rev: v2.1.0
Expand Down
44 changes: 39 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,49 @@ repository = "https://github.com/ubermag/ubermagutil"



[tool.black]
experimental-string-processing = true

[tool.coverage.run]
omit = ["ubermagutil/tests/*"]

[tool.isort]
profile = "black"
skip_gitignore = true # ignores files listed in .gitignore
[tool.ruff.lint]
ignore-init-module-imports = true # do not remove unused imports in __init__ and warn instead
select = [
"B", # flake8-bugbear
"E", # pycodestyle
"F", # Pyflakes
"I", # isort
"SIM", # flake8-simplify
"UP", # pyupgrade
]
ignore = [
# conflict with other rules
"D203", # one-blank-line-before-class (conflicts with D204)
"D212", # multi-line-summary-first-line (conflicts with D213)
# conflict with formatter
"D206", # indent-with-spaces
"D300", # triple-single-quotes
"E111", # indentation-with-invalid-multiple
"E114", # indentation-with-invalid-multiple-comment
"E117", # over-indented
# conflict with Python 3.6 compatibility
"UP022", # replace-stdout-stderr
]

[tool.ruff.lint.isort]
known-local-folder = ["ubermagutil"]

[tool.ruff.lint.per-file-ignores]
"*.ipynb" = [
"B018", # "Found useless expression. Either assign it to a variable or remove it."; false positives when using implicit __repr__ in the notebook
"E501", # line too long
"F811", # 'redefined-while-unused'; many false positives in notebooks because ipywidgets decorated functions are not recognised
]

[tool.pytest.ini_options]
filterwarnings = [
"error",
"ignore:((.|\n)*)Sentinel is not a public part of the traitlets API((.|\n)*)", # dependency of k3d
]

[tool.setuptools.packages.find]
include = ["ubermagutil*"]
Expand Down
28 changes: 0 additions & 28 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,30 +1,2 @@
[flake8]
exclude =
.git,
__pycache__,
build,
dev,
dist,
setup.py
# black has a longer default line length
max-line-length = 88
# D107: missing docstring in __init__
# E203: withespace before ':', required for black
# RST210: Inline strong start-string without end-string. # complains about "**kwargs" in docstrings
extend-ignore = D107,RST210,E203
per-file-ignores =
# imported but unused
__init__.py: F401
# ignore missing docstrings in tests
test_*.py: D100,D101,D102,D103
docstring-convention: numpy
# flake8-rst-docstrings:
rst-roles =
py:class,
py:func,
rst-directives =
seealso,
plot,

[codespell]
skip = .*,build/*,dev/*,dist/*
1 change: 1 addition & 0 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tasks to release the package."""

import os
import shutil

Expand Down
10 changes: 6 additions & 4 deletions ubermagutil/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Utilities used across Ubermag."""

import importlib.metadata

import pytest

from . import progress
from .basic_logging import setup_logging
from .inherit_docs import inherit_docs
from .tools import changedir, hysteresis_values
from . import progress as progress
from .basic_logging import setup_logging as setup_logging
from .inherit_docs import inherit_docs as inherit_docs
from .tools import changedir as changedir
from .tools import hysteresis_values as hysteresis_values

__version__ = importlib.metadata.version(__package__)

Expand Down
1 change: 1 addition & 0 deletions ubermagutil/basic_logging.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Setup basic logging for all ubermag packages."""

import logging


Expand Down
2 changes: 1 addition & 1 deletion ubermagutil/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def summary(package_name, runner_name):
yield
finally:
toc = time.time()
seconds = "({:0.1f} s)".format(toc - tic)
seconds = f"({toc - tic:0.1f} s)"
print(seconds) # append seconds to the previous print.


Expand Down
5 changes: 2 additions & 3 deletions ubermagutil/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ def test_hysteresis_values():


def test_changedir(tmp_path):
with uu.changedir(tmp_path):
with open("test.txt", "wt", encoding="utf-8") as f:
f.write("")
with uu.changedir(tmp_path), open("test.txt", "w", encoding="utf-8") as f:
f.write("")

assert (tmp_path / "test.txt").exists()
assert not (pathlib.Path() / "test.txt").exists()
1 change: 1 addition & 0 deletions ubermagutil/tools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Additional tools."""

import contextlib
import os

Expand Down
21 changes: 10 additions & 11 deletions ubermagutil/typesystem/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""Typesystem utility."""
from .descriptors import (
Descriptor,
Dictionary,
Name,
Parameter,
Scalar,
Subset,
Typed,
Vector,
)
from .typesystem import typesystem

from .descriptors import Descriptor as Descriptor
from .descriptors import Dictionary as Dictionary
from .descriptors import Name as Name
from .descriptors import Parameter as Parameter
from .descriptors import Scalar as Scalar
from .descriptors import Subset as Subset
from .descriptors import Typed as Typed
from .descriptors import Vector as Vector
from .typesystem import typesystem as typesystem
89 changes: 39 additions & 50 deletions ubermagutil/typesystem/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,9 @@ class Typed(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "allow_none"):
if self.allow_none and value is None:
super().__set__(instance, value)
return None
if hasattr(self, "allow_none") and self.allow_none and value is None:
super().__set__(instance, value)
return None
if not isinstance(value, self.expected_type):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
Expand Down Expand Up @@ -280,25 +279,21 @@ class Scalar(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "otherwise"):
if isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if hasattr(self, "otherwise") and isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if not isinstance(value, numbers.Real):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
if hasattr(self, "expected_type"):
if not isinstance(value, self.expected_type):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
if hasattr(self, "unsigned"):
if self.unsigned and value < 0:
msg = f"Cannot set {self.name} with value = {value} < 0."
raise ValueError(msg)
if hasattr(self, "positive"):
if self.positive and value <= 0:
msg = f"Cannot set {self.name} with value = {value} <= 0."
raise ValueError(msg)
if hasattr(self, "expected_type") and not isinstance(value, self.expected_type):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
if hasattr(self, "unsigned") and self.unsigned and value < 0:
msg = f"Cannot set {self.name} with value = {value} < 0."
raise ValueError(msg)
if hasattr(self, "positive") and self.positive and value <= 0:
msg = f"Cannot set {self.name} with value = {value} <= 0."
raise ValueError(msg)
super().__set__(instance, value)


Expand Down Expand Up @@ -390,30 +385,27 @@ class Vector(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "otherwise"):
if isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if hasattr(self, "otherwise") and isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if not isinstance(value, (tuple, list, np.ndarray)):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
if not all(isinstance(i, numbers.Real) for i in value):
msg = "Allowed only type(value[i]) == numbers.Real."
raise TypeError(msg)
if hasattr(self, "size"):
if len(value) != self.size:
msg = f"Cannot set {self.name} with length {len(value)} value."
raise ValueError(msg)
if hasattr(self, "component_type"):
if not all(isinstance(i, self.component_type) for i in value):
msg = f"Allowed only type(value[i]) == {self.component_type}."
raise TypeError(msg)
if hasattr(self, "unsigned"):
if self.unsigned and not all(i >= 0 for i in value):
raise ValueError("Allowed only value[i] >= 0.")
if hasattr(self, "positive"):
if self.positive and not all(i > 0 for i in value):
raise ValueError("Allowed only value[i] > 0.")
if hasattr(self, "size") and len(value) != self.size:
msg = f"Cannot set {self.name} with length {len(value)} value."
raise ValueError(msg)
if hasattr(self, "component_type") and any(
not isinstance(i, self.component_type) for i in value
):
msg = f"Allowed only type(value[i]) == {self.component_type}."
raise TypeError(msg)
if hasattr(self, "unsigned") and self.unsigned and any(i < 0 for i in value):
raise ValueError("Allowed only value[i] >= 0.")
if hasattr(self, "positive") and self.positive and any(i <= 0 for i in value):
raise ValueError("Allowed only value[i] > 0.")
super().__set__(instance, value)


Expand Down Expand Up @@ -572,10 +564,9 @@ class Dictionary(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "otherwise"):
if isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if hasattr(self, "otherwise") and isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if not isinstance(value, dict):
msg = f"Cannot set {self.name} with {type(value)}."
raise TypeError(msg)
Expand Down Expand Up @@ -652,10 +643,9 @@ class Parameter(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "otherwise"):
if isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if hasattr(self, "otherwise") and isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if isinstance(value, dict):
dictdescriptor = Dictionary(
key_descriptor=Name(allowed_char=":"), value_descriptor=self.descriptor
Expand Down Expand Up @@ -714,10 +704,9 @@ class Subset(Descriptor):
"""

def __set__(self, instance, value):
if hasattr(self, "otherwise"):
if isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if hasattr(self, "otherwise") and isinstance(value, self.otherwise):
super().__set__(instance, value)
return None
if self.unpack:
val = set(value)
if not val.issubset(self.sample_set):
Expand Down
2 changes: 1 addition & 1 deletion ubermagutil/typesystem/typesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def typesystem(**kwargs): # noqa: D401
def decorate(cls):
for key, value in kwargs.items():
if isinstance(value, Descriptor):
setattr(value, "name", key)
value.name = key
setattr(cls, key, value)
return cls

Expand Down
6 changes: 5 additions & 1 deletion ubermagutil/units/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
"""SI multiplier utility."""
from .units import rsi_prefixes, si_max_multiplier, si_multiplier, si_prefixes

from .units import rsi_prefixes as rsi_prefixes
from .units import si_max_multiplier as si_max_multiplier
from .units import si_multiplier as si_multiplier
from .units import si_prefixes as si_prefixes
3 changes: 2 additions & 1 deletion ubermagutil/units/units.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""SI multiplier utility."""

import collections

si_prefixes = collections.OrderedDict(
Expand Down Expand Up @@ -64,7 +65,7 @@ def si_multiplier(value):
if value == 0:
return 1
else:
for prefix, multiplier in reversed(si_prefixes.items()):
for _prefix, multiplier in reversed(si_prefixes.items()):
if 1 <= abs(value) / multiplier < 1e3:
return multiplier
else:
Expand Down

0 comments on commit 63ca281

Please sign in to comment.