diff --git a/Makefile b/Makefile index e2195782..ff2c1ceb 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache test: ## runs tests - poetry run pytest -s -vv -n 4 + poetry run pytest -vv -n 4 test-single: ## runs tests with "single" markers poetry run pytest -s -vv -m single diff --git a/poetry.lock b/poetry.lock index f1b923b7..3638f9f9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1221,13 +1221,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies] @@ -1235,11 +1235,11 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" @@ -1681,4 +1681,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "d2358097a9b58857f96af603a807c51687d355e45f9cab28e157afb545eff67d" +content-hash = "1c0a4c2cc913d45e5e7af3b44dec5b9aadd9ba77f4582a50d11a01a02e98bb00" diff --git a/pycardano/backend/base.py b/pycardano/backend/base.py index 04fe0eff..aec6948a 100644 --- a/pycardano/backend/base.py +++ b/pycardano/backend/base.py @@ -6,6 +6,7 @@ from pycardano.address import Address from pycardano.exception import InvalidArgumentException +from pycardano.logging import log_state from pycardano.network import Network from pycardano.plutus import ExecutionUnits from pycardano.transaction import Transaction, UTxO @@ -160,6 +161,7 @@ def _utxos(self, address: str) -> List[UTxO]: """ raise NotImplementedError() + @log_state def submit_tx(self, tx: Union[Transaction, bytes, str]): """Submit a transaction to the blockchain. diff --git a/pycardano/logging.py b/pycardano/logging.py index 349939bd..2cd369e5 100644 --- a/pycardano/logging.py +++ b/pycardano/logging.py @@ -1,14 +1,14 @@ import logging -__all__ = ["logger"] +from pprintpp import pformat + +__all__ = ["logger", "log_state"] # create logger logger = logging.getLogger("PyCardano") -logger.setLevel(logging.WARNING) # create console handler and set level to debug ch = logging.StreamHandler() -ch.setLevel(logging.WARNING) # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") @@ -18,3 +18,22 @@ # add ch to logger logger.addHandler(ch) + + +def log_state(func): + """Decorator to log the state of an object after its function call.""" + + def wrapper(obj, *args, **kwargs): + try: + output = func(obj, *args, **kwargs) + logger.debug( + f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}" + ) + return output + except Exception as e: + logger.warning( + f"Class: {obj.__class__}, method: {func}, state:\n {pformat(vars(obj), indent=2)}" + ) + raise e + + return wrapper diff --git a/pycardano/txbuilder.py b/pycardano/txbuilder.py index 2457c687..76c2168c 100644 --- a/pycardano/txbuilder.py +++ b/pycardano/txbuilder.py @@ -29,7 +29,7 @@ ) from pycardano.hash import DatumHash, ScriptDataHash, ScriptHash, VerificationKeyHash from pycardano.key import ExtendedSigningKey, SigningKey, VerificationKey -from pycardano.logging import logger +from pycardano.logging import log_state, logger from pycardano.metadata import AuxiliaryData from pycardano.nativescript import NativeScript, ScriptAll, ScriptAny, ScriptPubkey from pycardano.plutus import ( @@ -988,6 +988,7 @@ def _estimate_fee(self): return estimated_fee + @log_state def build( self, change_address: Optional[Address] = None, @@ -1357,6 +1358,7 @@ def _estimate_execution_units( return self.context.evaluate_tx(tx) + @log_state def build_and_sign( self, signing_keys: List[Union[SigningKey, ExtendedSigningKey]], diff --git a/pyproject.toml b/pyproject.toml index 1e8ccc4b..e0c6c38e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ docker = "^6.1.3" [tool.poetry.dev-dependencies] Sphinx = "^4.3.2" sphinx-rtd-theme = "^1.1.1" -pytest = "^7.4.4" +pytest = "^8.2.0" pytest-cov = "^4.0.0" flake8 = "^5.0.4" isort = "^5.11.4" @@ -67,6 +67,7 @@ markers = [ "single" ] + [tool.isort] profile = "black" diff --git a/test/pycardano/test_txbuilder.py b/test/pycardano/test_txbuilder.py index b09db3ca..373b57c5 100644 --- a/test/pycardano/test_txbuilder.py +++ b/test/pycardano/test_txbuilder.py @@ -1,4 +1,5 @@ import copy +import logging from dataclasses import replace from fractions import Fraction from test.pycardano.test_key import SK @@ -220,6 +221,30 @@ def test_tx_builder_raises_utxo_selection(chain_context): assert "{AssetName(b'NewToken'): 1}" in e.value.args[0] +def test_tx_builder_state_logger_warning_level(chain_context, caplog): + with caplog.at_level(logging.WARNING): + test_tx_builder_raises_utxo_selection(chain_context) + assert "WARNING" in caplog.text + + +def test_tx_builder_state_logger_error_level(chain_context, caplog): + with caplog.at_level(logging.ERROR): + test_tx_builder_raises_utxo_selection(chain_context) + assert "WARNING" not in caplog.text + + +def test_tx_builder_state_logger_info_level(chain_context, caplog): + with caplog.at_level(logging.INFO): + test_tx_builder_multi_asset(chain_context) + assert "DEBUG" not in caplog.text + + +def test_tx_builder_state_logger_debug_level(chain_context, caplog): + with caplog.at_level(logging.DEBUG): + test_tx_builder_multi_asset(chain_context) + assert "DEBUG" in caplog.text + + def test_tx_too_big_exception(chain_context): tx_builder = TransactionBuilder(chain_context) sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"