From b4caec81bf4799292c9e20a932209b55a3e7747f Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:56:36 +0200 Subject: [PATCH 01/10] Adding latest changes from `mapdl.math` --- src/ansys/math/core/math.py | 82 ++++++++++++++++++++++++++++++++++--- tests/test_math.py | 34 +++++++++++++++ 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/src/ansys/math/core/math.py b/src/ansys/math/core/math.py index 71c624ca..d2000618 100644 --- a/src/ansys/math/core/math.py +++ b/src/ansys/math/core/math.py @@ -1349,6 +1349,52 @@ def axpy(self, obj, val1, val2): self._mapdl.run(f"*AXPY,{val1},0,{obj.id},{val2},0,{self.id}", mute=True) return self + def kron(self, obj): + """Calculates the Kronecker product of two matrices/vectors + + Parameters + ---------- + obj : ``AnsVec`` or ``AnsMat`` + AnsMath object. + + Returns + ------- + ``AnsMat`` or ``AnsVec`` + Kronecker product between the two matrices/vectors. + + .. note:: + Requires at least MAPDL version 2023R2. + + Examples + -------- + >>> mm = mapdl.math + >>> m1 = mm.rand(3, 3) + >>> m2 = mm.rand(4,2) + >>> res = m1.kron(m2) + """ + + mapdl_version = self._mapdl.version + if mapdl_version < 23.2: # pragma: no cover + raise VersionError("``kron`` requires MAPDL version 2023R2") + + if not isinstance(obj, AnsMath): + raise TypeError("Must be an AnsMath object.") + + if not isinstance(self, (AnsMat, AnsVec)): + raise TypeError(f"Kron product aborted: Unknown obj type ({self.type})") + if not isinstance(obj, (AnsMat, AnsVec)): + raise TypeError(f"Kron product aborted: Unknown obj type ({obj.type})") + + name = id_generator() # internal name of the new vector/matrix + # perform the Kronecker product + self._mapdl.run(f"*KRON,{self.id},{obj.id},{name}") + + if isinstance(self, AnsVec) and isinstance(obj, AnsVec): + objout = AnsVec(name, self._mapdl) + else: + objout = AnsMat(name, self._mapdl) + return objout + def __add__(self, op2): if not hasattr(op2, "id"): raise TypeError("The object to be added must be an AnsMath object.") @@ -1377,8 +1423,20 @@ def __isub__(self, op): return self.axpy(op, -1, 1) def __imul__(self, val): - self._mapdl._log.info("Call MAPDL to scale the object.") - self._mapdl.run(f"*SCAL,{self.id},{val}", mute=True) + mapdl_version = self._mapdl.version + self._mapdl._log.info("Call Mapdl to scale the object") + + if isinstance(val, AnsVec): + if mapdl_version < 23.2: # pragma: no cover + raise VersionError("Scaling by a vector requires MAPDL version 2023R2 or superior.") + else: + self._mapdl._log.info(f"Scaling ({self.type}) by a vector") + self._mapdl.run(f"*SCAL,{self.id},{val.id}", mute=False) + elif isinstance(val, (int, float)): + self._mapdl.run(f"*SCAL,{self.id},{val}", mute=True) + else: + raise TypeError(f"The provided type {type(val)} is not supported.") + return self def __itruediv__(self, val): @@ -1427,10 +1485,24 @@ def __repr__(self): return f"AnsMath vector size {self.size}" def __getitem__(self, num): + info = self._mapdl._data_info(self.id) + dtype = ANSYS_VALUE_TYPE[info.stype] if num < 0: - raise ValueError("Negative indices are not permitted.") - self._mapdl.run(f"pyval={self.id}({num+1})", mute=True) - return self._mapdl.scalar_param("pyval") + raise ValueError("Negative indices not permitted") + + self._mapdl.run(f"pyval_={self.id}({num+1})", mute=True) + item_val = self._mapdl.scalar_param("pyval_") + + if MYCTYPE[dtype].upper() in ["C", "Z"]: + self._mapdl.run(f"pyval_img_={self.id}({num+1},2)", mute=True) + img_val = self._mapdl.scalar_param("pyval_img_") + item_val = item_val + img_val * 1j + + # Clean parameters + self._mapdl.run("item_val =") + self._mapdl.run("pyval_img_=") + + return item_val def __mul__(self, vec): """Return the element-wise product with another AnsMath vector. diff --git a/tests/test_math.py b/tests/test_math.py index fbeb8323..db445804 100644 --- a/tests/test_math.py +++ b/tests/test_math.py @@ -222,6 +222,40 @@ def test_getitem(mm): assert vec[j] == np_mat[j, i] +@pytest.mark.parametrize("dtype_", [np.double, np.complex128]) +def test_kron_product(mm, dtype_): + mapdl_version = mm._mapdl.version + if mapdl_version < 23.2: + pytest.skip("Requires MAPDL 2023 R2 or later.") + + m1 = mm.rand(3, 3, dtype=dtype_) + m2 = mm.rand(2, 2, dtype=dtype_) + v1 = mm.rand(2, dtype=dtype_) + v2 = mm.rand(4, dtype=dtype_) + # *kron product between matrix and another matrix + res1 = m1.kron(m2) + + # *kron product between Vector and a matrix + res2 = v1.kron(m2) + + # *kron product between Vector and another Vector + res3 = v1.kron(v2) + + assert np.allclose(res1.asarray(), np.kron(m1, m2)) + assert np.allclose(res2.asarray(), np.kron(v1.asarray().reshape(2, 1), m2)) + assert np.allclose(res3.asarray(), np.kron(v1, v2)) + + +def test_kron_product_unsupported_dtype(mm): + mapdl_version = mm._mapdl.version + if mapdl_version < 23.2: + pytest.skip("Requires MAPDL 2023 R2 or later.") + + with pytest.raises(TypeError, match=r"Must be an ApdlMathObj"): + m1 = mm.rand(3, 3) + m1.kron(2) + + def test_load_stiff_mass(mm, cube_solve, tmpdir): k = mm.stiff() m = mm.mass() From 9778ab475e85d95f0193ecbd1a1e128941d794c8 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:18:19 +0200 Subject: [PATCH 02/10] Fixing typos --- src/ansys/math/core/math.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ansys/math/core/math.py b/src/ansys/math/core/math.py index d2000618..a0d232c0 100644 --- a/src/ansys/math/core/math.py +++ b/src/ansys/math/core/math.py @@ -630,7 +630,9 @@ def mass( Examples -------- - >>> mass = mapdl.math.mass() + >>> import ansys.math.core.math as pymath + >>> mm = pymath.AnsMath() + >>> mass = mm.mass() >>> mass AnsMath matrix 60 x 60 @@ -672,7 +674,9 @@ def damp( Examples -------- - >>> ans_mat = mapdl.math.damp() + >>> import ansys.math.core.math as pymath + >>> mm = pymath.AnsMath() + >>> ans_mat = mm.damp() >>> ans_mat AnsMath Matrix 60 x 60 @@ -1367,7 +1371,8 @@ def kron(self, obj): Examples -------- - >>> mm = mapdl.math + >>> import ansys.math.core.math as pymath + >>> mm = pymath.AnsMath() >>> m1 = mm.rand(3, 3) >>> m2 = mm.rand(4,2) >>> res = m1.kron(m2) @@ -1424,7 +1429,7 @@ def __isub__(self, op): def __imul__(self, val): mapdl_version = self._mapdl.version - self._mapdl._log.info("Call Mapdl to scale the object") + self._mapdl._log.info("Call MAPDL to scale the object") if isinstance(val, AnsVec): if mapdl_version < 23.2: # pragma: no cover From cd64eb569b5415600539e18c3f0a065c0d3f1ac0 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:58:59 +0200 Subject: [PATCH 03/10] Removing `Mapdl` from the Ansys Vocab --- doc/styles/Vocab/ANSYS/accept.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/styles/Vocab/ANSYS/accept.txt b/doc/styles/Vocab/ANSYS/accept.txt index 27ad776c..08cc05b6 100644 --- a/doc/styles/Vocab/ANSYS/accept.txt +++ b/doc/styles/Vocab/ANSYS/accept.txt @@ -17,7 +17,6 @@ Eigenshape eigenshapes eigensolvers MAPDL -Mapdl mapdl my_mat nax From f8982aadd849ff40d78c000206a74ef445c6e98d Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:39:17 +0200 Subject: [PATCH 04/10] Adding updates --- src/ansys/math/core/math.py | 17 +++++++++++++++-- tests/test_math.py | 13 +++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/ansys/math/core/math.py b/src/ansys/math/core/math.py index a0d232c0..f8b53db2 100644 --- a/src/ansys/math/core/math.py +++ b/src/ansys/math/core/math.py @@ -904,7 +904,18 @@ def sparse(self, mat, thresh="", **kwargs): kwargs.setdefault("mute", True) self._mapdl.run(f"*COMP,{mat.id},SPARSE,{thresh}", **kwargs) - def eigs(self, nev, k, m=None, c=None, phi=None, algo=None, fmin=None, fmax=None): + def eigs( + self, + nev, + k, + m=None, + c=None, + phi=None, + algo=None, + fmin=None, + fmax=None, + cpxmod=None, + ): """Solve an eigenproblem. Parameters @@ -935,6 +946,8 @@ def eigs(self, nev, k, m=None, c=None, phi=None, algo=None, fmin=None, fmax=None fmin = "" if not fmax: fmax = "" + if not cpxmod: + cpxmod = "" cid = "" if not c: @@ -949,7 +962,7 @@ def eigs(self, nev, k, m=None, c=None, phi=None, algo=None, fmin=None, fmax=None self._mapdl.run("/SOLU", mute=True) self._mapdl.run("antype,modal", mute=True) - self._mapdl.run(f"modopt,{algo},{nev},{fmin},{fmax}", mute=True) + self._mapdl.run(f"modopt,{algo},{nev},{fmin},{fmax},{cpxmod}", mute=True) ev = self.vec() phistr = "" if not phi else phi.id diff --git a/tests/test_math.py b/tests/test_math.py index db445804..38a88040 100644 --- a/tests/test_math.py +++ b/tests/test_math.py @@ -73,6 +73,19 @@ def test_inplace_mult(mm): assert v[0] == 2 +def test_inplace_mult_with_vec(mm): + mapdl_version = mm._mapdl.version + if mapdl_version < 23.2: + pytest.skip("Requires MAPDL 2023 R2 or later.") + + m1 = mm.rand(3, 3) + m2 = m1.copy() + v1 = mm.ones(3) + v1.const(2) + m2 *= v1 + assert np.allclose(m2, np.multiply(m1, v1) * v1) + + def test_set_vec_large(mm): # send a vector larger than the gRPC size limit of 4 MB sz = 1000000 From e2720dce8a45d170ecb55c6a9270e4643cae43b9 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:23:09 +0200 Subject: [PATCH 05/10] Adding unit tests --- tests/test_files/model_damping.db | Bin 0 -> 2228224 bytes tests/test_math.py | 79 +++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/test_files/model_damping.db diff --git a/tests/test_files/model_damping.db b/tests/test_files/model_damping.db new file mode 100644 index 0000000000000000000000000000000000000000..53cade7bb8a125cb111abbe155e920db777241ff GIT binary patch literal 2228224 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 z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs 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 0 for each in d.shape]) + + d = mm.damp(asarray=True) + assert sparse.issparse(d) + assert all([each > 0 for each in d.shape]) + + +@pytest.mark.parametrize("dtype_", [np.int64, np.double]) +def test_damp_matrix_dtype(mm, cube_with_damping, dtype_): + d = mm.stiff(asarray=True, dtype=dtype_) + + assert sparse.issparse(d) + assert all([each > 0 for each in d.shape]) + assert d.dtype == dtype_ + + d = mm.stiff(dtype=dtype_) + d = d.asarray(dtype=dtype_) + + assert sparse.issparse(d) + assert all([each > 0 for each in d.shape]) + assert d.dtype == dtype_ + + @pytest.fixture(scope="module") def exit(mm): return mm._mapdl.exit() From d95b8690426bb839710ce20b24b76de5ab19530a Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:54:57 +0200 Subject: [PATCH 06/10] Updating `pre-commit-config` --- .pre-commit-config.yaml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13cd1914..8f3a780a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,14 @@ +fail_fast: True + repos: +- repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort - repo: https://github.com/psf/black - rev: 23.1.0 + rev: 23.3.0 # IF VERSION CHANGES --> MODIFY "blacken-docs" MANUALLY AS WELL!! hooks: - id: black args: @@ -12,21 +18,12 @@ repos: rev: 1.13.0 hooks: - id: blacken-docs - additional_dependencies: [black==22.12.0] - args: - - --line-length=100 - -- repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort + additional_dependencies: [black==23.3.0] - repo: https://github.com/PyCQA/flake8 rev: 6.0.0 hooks: - id: flake8 - args: - - --max-line-length=120 - repo: https://github.com/codespell-project/codespell rev: v2.2.4 @@ -35,8 +32,6 @@ repos: args: ["--toml", "pyproject.toml"] additional_dependencies: ["tomli"] -# To be activated after quick dev cycles -# # - repo: https://github.com/pycqa/pydocstyle # rev: 6.1.1 # hooks: @@ -52,6 +47,6 @@ repos: # this validates our github workflow files - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.22.0 + rev: 0.23.1 hooks: - - id: check-github-workflows + - id: check-github-workflows \ No newline at end of file From b8d80f451e24d56c4885bcff07c2ca0ab1986ee6 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:31:01 +0200 Subject: [PATCH 07/10] Fixing pre-commit --- .flake8 | 2 +- pyproject.toml | 10 +++++----- src/ansys/math/core/math.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.flake8 b/.flake8 index 69da4e29..7f94b821 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = venv, __init__.py, doc/_build, .venv, doc/source/examples +exclude = venv, __init__.py, doc/_build, .venv, doc/source/examples, conf.py select = W191, W291, W293, W391, E115, E117, E122, E124, E125, E225, E231, E301, E303, E501, F401, F403 count = True max-complexity = 10 diff --git a/pyproject.toml b/pyproject.toml index d17640c9..2607beab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,9 @@ maintainers = [ {name = "ANSYS, Inc.", email = "pyansys.core@ansys.com"}, ] classifiers=[ + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Information Analysis", + "License :: OSI Approved :: MIT License", "Development Status :: 4 - Beta", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -74,14 +77,11 @@ Documentation = "https://math.docs.pyansys.com" Source = "https://github.com/ansys/ansys-math" Tracker = "https://github.com/ansys/ansys-math/issues" -[tool.black] -line-length = 100 - [tool.isort] profile = "black" force_sort_within_sections = true -line_length = 100 default_section = "THIRDPARTY" +skip_glob = ["__init__.py"] src_paths = ["doc", "src", "tests"] [tool.coverage.run] @@ -91,6 +91,6 @@ source = ["ansys/pyansys-math"] show_missing = true [tool.codespell] -skip = '*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,build,./docker/mapdl/v*,./factory/*,./ansys/mapdl/core/mapdl_functions.py,PKG-INFO,*.mypy_cache/*,./docker/mapdl/*,./_unused/*' +skip = '*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,build,./docker/mapdl/v*,./factory/*,PKG-INFO,*.mypy_cache/*,./docker/mapdl/*,./_unused/*' ignore-words = "doc/styles/Vocab/ANSYS/accept.txt" quiet-level = 3 diff --git a/src/ansys/math/core/math.py b/src/ansys/math/core/math.py index 1f0dbd64..a3c86292 100644 --- a/src/ansys/math/core/math.py +++ b/src/ansys/math/core/math.py @@ -1597,8 +1597,8 @@ def asarray(self, dtype=None) -> np.ndarray: ---------- dtype : numpy.dtype, optional NumPy data type to upload the array as. The options are `np.double `_, - `np.int32 `_, and `np.int64 `_. The default is the current array - type. + `np.int32 `_, and `np.int64 `_. The default is the current + array type. Returns ------- From e511274d34338dafb1395bf1edbdf1ab18355a83 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:39:22 +0200 Subject: [PATCH 08/10] Adding github checks --- codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov.yml b/codecov.yml index 398b0ed7..8079553d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,6 +2,7 @@ comment: layout: "diff" behavior: default require_changes: true # Avoid coverage comment if no files are changed. + github_checks: true coverage: range: 70..100 From 25986668dc19509f2304b60935cd89a7dc75f25b Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:43:34 +0200 Subject: [PATCH 09/10] Codecov changes --- codecov.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 8079553d..dd7ec859 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,8 +1,9 @@ +github_checks: true + comment: layout: "diff" behavior: default require_changes: true # Avoid coverage comment if no files are changed. - github_checks: true coverage: range: 70..100 From 317b879545360f7adcf622bc496957d8242eb14e Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 9 Jun 2023 17:24:09 +0200 Subject: [PATCH 10/10] Reverting the commites related to codecov --- .flake8 | 2 +- .pre-commit-config.yaml | 25 +++++++++++++++---------- codecov.yml | 2 -- pyproject.toml | 10 +++++----- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.flake8 b/.flake8 index 7f94b821..69da4e29 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = venv, __init__.py, doc/_build, .venv, doc/source/examples, conf.py +exclude = venv, __init__.py, doc/_build, .venv, doc/source/examples select = W191, W291, W293, W391, E115, E117, E122, E124, E125, E225, E231, E301, E303, E501, F401, F403 count = True max-complexity = 10 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f3a780a..5051f5b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,8 @@ -fail_fast: True - repos: -- repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - repo: https://github.com/psf/black - rev: 23.3.0 # IF VERSION CHANGES --> MODIFY "blacken-docs" MANUALLY AS WELL!! + rev: 23.1.0 hooks: - id: black args: @@ -18,12 +12,21 @@ repos: rev: 1.13.0 hooks: - id: blacken-docs - additional_dependencies: [black==23.3.0] + additional_dependencies: [black==22.12.0] + args: + - --line-length=100 + +- repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort - repo: https://github.com/PyCQA/flake8 rev: 6.0.0 hooks: - id: flake8 + args: + - --max-line-length=120 - repo: https://github.com/codespell-project/codespell rev: v2.2.4 @@ -32,6 +35,8 @@ repos: args: ["--toml", "pyproject.toml"] additional_dependencies: ["tomli"] +# To be activated after quick dev cycles +# # - repo: https://github.com/pycqa/pydocstyle # rev: 6.1.1 # hooks: @@ -47,6 +52,6 @@ repos: # this validates our github workflow files - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.23.1 + rev: 0.22.0 hooks: - - id: check-github-workflows \ No newline at end of file + - id: check-github-workflows \ No newline at end of file diff --git a/codecov.yml b/codecov.yml index dd7ec859..398b0ed7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,5 +1,3 @@ -github_checks: true - comment: layout: "diff" behavior: default diff --git a/pyproject.toml b/pyproject.toml index 2607beab..d17640c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,9 +17,6 @@ maintainers = [ {name = "ANSYS, Inc.", email = "pyansys.core@ansys.com"}, ] classifiers=[ - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering :: Information Analysis", - "License :: OSI Approved :: MIT License", "Development Status :: 4 - Beta", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -77,11 +74,14 @@ Documentation = "https://math.docs.pyansys.com" Source = "https://github.com/ansys/ansys-math" Tracker = "https://github.com/ansys/ansys-math/issues" +[tool.black] +line-length = 100 + [tool.isort] profile = "black" force_sort_within_sections = true +line_length = 100 default_section = "THIRDPARTY" -skip_glob = ["__init__.py"] src_paths = ["doc", "src", "tests"] [tool.coverage.run] @@ -91,6 +91,6 @@ source = ["ansys/pyansys-math"] show_missing = true [tool.codespell] -skip = '*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,build,./docker/mapdl/v*,./factory/*,PKG-INFO,*.mypy_cache/*,./docker/mapdl/*,./_unused/*' +skip = '*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,build,./docker/mapdl/v*,./factory/*,./ansys/mapdl/core/mapdl_functions.py,PKG-INFO,*.mypy_cache/*,./docker/mapdl/*,./_unused/*' ignore-words = "doc/styles/Vocab/ANSYS/accept.txt" quiet-level = 3