diff --git a/pyproject.toml b/pyproject.toml index 90b11c06..b92cdb18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,9 +5,7 @@ build-backend = "hatchling.build" [project] name = "formulaic" description = "An implementation of Wilkinson formulas." -authors = [ - {name = "Matthew Wardrop", email = "mpwardrop@gmail.com"}, -] +authors = [{ name = "Matthew Wardrop", email = "mpwardrop@gmail.com" }] license = "MIT" readme = "README.md" classifiers = [ @@ -105,22 +103,15 @@ dependencies = [ ] [tool.hatch.envs.lint] -dependencies = [ - "mypy==1.11.1", - "mypy-extensions==1.0.0", - "ruff==0.5.6", -] +dependencies = ["mypy==1.11.1", "mypy-extensions==1.0.0", "ruff==0.5.6"] [tool.hatch.envs.lint.scripts] -check = [ - "ruff check", - "ruff format --check", - "mypy formulaic", -] -format = [ - "ruff check --fix", - "ruff format", -] +check = ["ruff check", "ruff format --check", "mypy formulaic"] +format = ["ruff check --fix", "ruff format"] + +# Coverage configuration +[tool.coverage.run] +omit = ["formulaic/_version.py"] # Linting configuration @@ -141,11 +132,11 @@ exclude = [ [tool.ruff.lint] select = [ - "F", # flake8 rules - "E", # pycodestyle - "W", # pycodestyle - "S", # bandit - "I001", # import sorting + "F", # flake8 rules + "E", # pycodestyle + "W", # pycodestyle + "S", # bandit + "I001", # import sorting # "D", # documentation ] @@ -156,7 +147,7 @@ ignore = [ "E712", "E722", "E731", - "S307", # Use of ast.literal_eval + "S307", # Use of ast.literal_eval ] [tool.ruff.lint.per-file-ignores] diff --git a/tests/parser/types/test_operator_resolver.py b/tests/parser/types/test_operator_resolver.py index aca53366..3a7b6370 100644 --- a/tests/parser/types/test_operator_resolver.py +++ b/tests/parser/types/test_operator_resolver.py @@ -1,3 +1,5 @@ +import re + import pytest from formulaic.errors import FormulaParsingError, FormulaSyntaxError @@ -28,3 +30,6 @@ def resolver(self): def test_resolve(self, resolver): assert list(resolver.resolve(Token("+")))[0][1][0] is OPERATOR_PLUS assert list(resolver.resolve(Token("-")))[0][1][0] is OPERATOR_UNARY_MINUS + + with pytest.raises(FormulaSyntaxError, match=re.escape("Unknown operator '&'")): + list(resolver.resolve(Token("&"))) diff --git a/tests/transforms/test_scale.py b/tests/transforms/test_scale.py index 098029fe..53ce2abf 100644 --- a/tests/transforms/test_scale.py +++ b/tests/transforms/test_scale.py @@ -1,3 +1,5 @@ +import re + import numpy import pytest import scipy.sparse as spsparse @@ -41,6 +43,13 @@ def test_scale(): ) assert state == {"center": 1, "scale": 2, "ddof": 1} + # Make sure we raise for sparse matrices with more than one column + with pytest.raises( + ValueError, + match=re.escape("Cannot scale a sparse matrix with more than one column."), + ): + scale(data=spsparse.csc_matrix([[1, 2, 3], [4, 5, 6]]), center=[1, 2, 3]) + def test_center(): state = {} diff --git a/tests/utils/test_calculus.py b/tests/utils/test_calculus.py index b7122c33..62b9f933 100644 --- a/tests/utils/test_calculus.py +++ b/tests/utils/test_calculus.py @@ -1,7 +1,9 @@ +import re + import pytest from formulaic.parser.types import Factor, Term -from formulaic.utils.calculus import differentiate_term +from formulaic.utils.calculus import differentiate_term, _differentiate_factors def test_differentiate_term(): @@ -21,3 +23,12 @@ def test_differentiate_term_with_sympy(): str(differentiate_term(t, ["log(b)"], use_sympy=True)) == "0" ) # 'log(b)' is not in the free symbol list. assert str(differentiate_term(t, ["b"], use_sympy=True)) == "a:(1/b)" + + +def test__differentiate_factors(): + t = Term([Factor("a"), Factor("log(a)")]) + + assert _differentiate_factors(t.factors, "a", use_sympy=True) == {"(log(a) + 1)"} + + with pytest.raises(RuntimeError, match=re.escape("Cannot differentiate non-trivial factors without `sympy`.")): + _differentiate_factors(t.factors, "a", use_sympy=False)