diff --git a/diceplayer/__main__.py b/diceplayer/__main__.py index acafd25..538be5f 100644 --- a/diceplayer/__main__.py +++ b/diceplayer/__main__.py @@ -1,12 +1,12 @@ -import yaml - from diceplayer.config.player_config import PlayerConfig from diceplayer.logger import logger +from diceplayer.player import Player + +import yaml import argparse from importlib import metadata -from diceplayer.player import Player VERSION = metadata.version("diceplayer") diff --git a/diceplayer/environment/molecule.py b/diceplayer/environment/molecule.py index 4338599..5ae59ea 100644 --- a/diceplayer/environment/molecule.py +++ b/diceplayer/environment/molecule.py @@ -1,7 +1,7 @@ from __future__ import annotations -from diceplayer.logger import logger from diceplayer.environment import Atom +from diceplayer.logger import logger from diceplayer.utils.cache import invalidate_computed_properties from diceplayer.utils.misc import BOHR2ANG, EA_2_DEBYE from diceplayer.utils.ptable import GHOST_NUMBER diff --git a/diceplayer/utils/logger.py b/diceplayer/utils/logger.py index d18be42..51bcb8c 100644 --- a/diceplayer/utils/logger.py +++ b/diceplayer/utils/logger.py @@ -1,7 +1,9 @@ +from typing_extensions import TypeVar + import logging import sys from pathlib import Path -from typing_extensions import TypeVar + H = TypeVar('H', bound=logging.Handler) diff --git a/pyproject.toml b/pyproject.toml index 18300a1..cd38329 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,8 @@ dev = [ "black>=24.4.2", "pre-commit>=3.7.1", "poethepoet>=0.27.0", - "ruff>=0.15.2" + "ruff>=0.15.2", + "pytest>=9.0.2", ] @@ -79,4 +80,4 @@ lines-after-imports = 2 [tool.pyright] venvPath = "." -venv = ".venv" \ No newline at end of file +venv = ".venv" diff --git a/tests/config/test_dice_dto.py b/tests/config/test_dice_config.py similarity index 61% rename from tests/config/test_dice_dto.py rename to tests/config/test_dice_config.py index 3cd4f23..8afe05e 100644 --- a/tests/config/test_dice_dto.py +++ b/tests/config/test_dice_config.py @@ -1,9 +1,9 @@ from diceplayer.config.dice_config import DiceConfig -import unittest +import pytest -class TestDiceDto(unittest.TestCase): +class TestDiceConfig: def test_class_instantiation(self): dice_dto = DiceConfig( ljname="test", @@ -13,10 +13,10 @@ class TestDiceDto(unittest.TestCase): nstep=[1, 1], ) - self.assertIsInstance(dice_dto, DiceConfig) + assert isinstance(dice_dto, DiceConfig) def test_validate_jname(self): - with self.assertRaises(ValueError) as ex: + with pytest.raises(ValueError) as ex: DiceConfig( ljname=None, outname="test", @@ -24,12 +24,11 @@ class TestDiceDto(unittest.TestCase): nmol=[1], nstep=[1, 1], ) - self.assertEqual( - ex.exception, "Error: 'ljname' keyword not specified in config file" - ) + + assert ex.value == "Error: 'ljname' keyword not specified in config file" def test_validate_outname(self): - with self.assertRaises(ValueError) as ex: + with pytest.raises(ValueError) as ex: DiceConfig( ljname="test", outname=None, @@ -37,12 +36,11 @@ class TestDiceDto(unittest.TestCase): nmol=[1], nstep=[1, 1], ) - self.assertEqual( - ex.exception, "Error: 'outname' keyword not specified in config file" - ) + + assert ex.value == "Error: 'outname' keyword not specified in config file" def test_validate_dens(self): - with self.assertRaises(ValueError) as ex: + with pytest.raises(ValueError) as ex: DiceConfig( ljname="test", outname="test", @@ -50,12 +48,11 @@ class TestDiceDto(unittest.TestCase): nmol=[1], nstep=[1, 1], ) - self.assertEqual( - ex.exception, "Error: 'dens' keyword not specified in config file" - ) + + assert ex.value == "Error: 'dens' keyword not specified in config file" def test_validate_nmol(self): - with self.assertRaises(ValueError) as ex: + with pytest.raises(ValueError) as ex: DiceConfig( ljname="test", outname="test", @@ -63,13 +60,11 @@ class TestDiceDto(unittest.TestCase): nmol=0, nstep=[1, 1], ) - self.assertEqual( - ex.exception, - "Error: 'nmol' keyword not defined appropriately in config file", - ) + + assert ex.value == "Error: 'nmol' keyword not specified in config file" def test_validate_nstep(self): - with self.assertRaises(ValueError) as ex: + with pytest.raises(ValueError) as ex: DiceConfig( ljname="test", outname="test", @@ -77,10 +72,8 @@ class TestDiceDto(unittest.TestCase): nmol=[1], nstep=0, ) - self.assertEqual( - ex.exception, - "Error: 'nstep' keyword not defined appropriately in config file", - ) + + assert ex.value == "Error: 'nstep' keyword not specified in config file" def test_from_dict(self): dice_dto = DiceConfig.model_validate( @@ -93,4 +86,4 @@ class TestDiceDto(unittest.TestCase): } ) - self.assertIsInstance(dice_dto, DiceConfig) + assert isinstance(dice_dto, DiceConfig) diff --git a/tests/config/test_gaussian_dto.py b/tests/config/test_gaussian_config.py similarity index 71% rename from tests/config/test_gaussian_dto.py rename to tests/config/test_gaussian_config.py index f45fcdf..707fc4c 100644 --- a/tests/config/test_gaussian_dto.py +++ b/tests/config/test_gaussian_config.py @@ -1,9 +1,9 @@ from diceplayer.config.gaussian_config import GaussianConfig -import unittest +import pytest -class TestGaussianDTO(unittest.TestCase): +class TestGaussianConfig: def test_class_instantiation(self): gaussian_dto = GaussianConfig( level="test", @@ -11,10 +11,10 @@ class TestGaussianDTO(unittest.TestCase): keywords="test", ) - self.assertIsInstance(gaussian_dto, GaussianConfig) + assert isinstance(gaussian_dto, GaussianConfig) def test_is_valid_qmprog(self): - with self.assertRaises(ValueError): + with pytest.raises(ValueError): GaussianConfig( level="test", qmprog="test", @@ -22,7 +22,7 @@ class TestGaussianDTO(unittest.TestCase): ) def test_is_valid_level(self): - with self.assertRaises(ValueError): + with pytest.raises(ValueError): GaussianConfig( level=None, qmprog="g16", @@ -38,8 +38,4 @@ class TestGaussianDTO(unittest.TestCase): } ) - self.assertIsInstance(gaussian_dto, GaussianConfig) - - -if __name__ == "__main__": - unittest.main() + assert isinstance(gaussian_dto, GaussianConfig) diff --git a/tests/config/test_player_dto.py b/tests/config/test_player_config.py similarity index 60% rename from tests/config/test_player_dto.py rename to tests/config/test_player_config.py index 883fad0..93f18df 100644 --- a/tests/config/test_player_dto.py +++ b/tests/config/test_player_config.py @@ -2,7 +2,7 @@ from diceplayer.config.dice_config import DiceConfig from diceplayer.config.gaussian_config import GaussianConfig from diceplayer.config.player_config import PlayerConfig -import unittest +import pytest def get_config_dict(): @@ -27,37 +27,41 @@ def get_config_dict(): } -class TestPlayerDTO(unittest.TestCase): - def setUp(self) -> None: - self.dice_dto = DiceConfig( +class TestPlayerConfig: + @pytest.fixture + def dice_config(self): + return DiceConfig( ljname="test", outname="test", dens=1.0, nmol=[1], nstep=[1, 1], ) - self.gaussian_dto = GaussianConfig( + + @pytest.fixture + def gaussian_config(self): + return GaussianConfig( level="test", qmprog="g16", keywords="test", ) - def test_class_instantiation(self): + def test_class_instantiation(self, dice_config, gaussian_config): player_dto = PlayerConfig( opt=True, mem=12, maxcyc=100, nprocs=4, ncores=4, - dice=self.dice_dto, - gaussian=self.gaussian_dto, + dice=dice_config, + gaussian=gaussian_config, ) - self.assertIsInstance(player_dto, PlayerConfig) - self.assertIsInstance(player_dto.dice, DiceConfig) - self.assertIsInstance(player_dto.gaussian, GaussianConfig) + assert isinstance(player_dto, PlayerConfig) + assert isinstance(player_dto.dice, DiceConfig) + assert isinstance(player_dto.gaussian, GaussianConfig) - def test_min_altsteps(self): + def test_min_altsteps(self, dice_config, gaussian_config): player_dto = PlayerConfig( opt=True, mem=12, @@ -65,19 +69,15 @@ class TestPlayerDTO(unittest.TestCase): nprocs=4, ncores=4, altsteps=100, - dice=self.dice_dto, - gaussian=self.gaussian_dto, + dice=dice_config, + gaussian=gaussian_config, ) - self.assertEqual(player_dto.altsteps, 20000) + assert player_dto.altsteps == 20000 def test_from_dict(self): player_dto = PlayerConfig.model_validate(get_config_dict()) - self.assertIsInstance(player_dto, PlayerConfig) - self.assertIsInstance(player_dto.dice, DiceConfig) - self.assertIsInstance(player_dto.gaussian, GaussianConfig) - - -if __name__ == "__main__": - unittest.main() + assert isinstance(player_dto, PlayerConfig) + assert isinstance(player_dto.dice, DiceConfig) + assert isinstance(player_dto.gaussian, GaussianConfig) diff --git a/uv.lock b/uv.lock index aa2f70b..64dc6d0 100644 --- a/uv.lock +++ b/uv.lock @@ -231,6 +231,7 @@ dev = [ { name = "isort" }, { name = "poethepoet" }, { name = "pre-commit" }, + { name = "pytest" }, { name = "ruff" }, ] @@ -251,6 +252,7 @@ dev = [ { name = "isort", specifier = ">=5.13.2" }, { name = "poethepoet", specifier = ">=0.27.0" }, { name = "pre-commit", specifier = ">=3.7.1" }, + { name = "pytest", specifier = ">=9.0.2" }, { name = "ruff", specifier = ">=0.15.2" }, ] @@ -263,6 +265,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, ] +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + [[package]] name = "filelock" version = "3.24.3" @@ -281,6 +295,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b8/58/40fbbcefeda82364720eba5cf2270f98496bdfa19ea75b4cccae79c698e6/identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0", size = 99202, upload-time = "2026-01-12T18:58:56.627Z" }, ] +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + [[package]] name = "isort" version = "8.0.1" @@ -491,6 +514,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, ] +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + [[package]] name = "poethepoet" version = "0.42.1" @@ -654,6 +686,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, +] + [[package]] name = "python-discovery" version = "1.1.0"