diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e75f70c..f28d8a6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: matrix: python-version: [3.9] requirements-level: [pypi] - db-service: [postgresql13, postgres14] + db-service: [postgresql13, postgresql14] search-service: [elasticsearch7, opensearch2] include: - search-service: opensearch2 diff --git a/docs/conf.py b/docs/conf.py index 14e9e06..f73d0d7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,7 @@ import os import sphinx.environment + from invenio_circulation import __version__ # -- General configuration ------------------------------------------------ diff --git a/invenio_circulation/config.py b/invenio_circulation/config.py index e684fac..9292366 100644 --- a/invenio_circulation/config.py +++ b/invenio_circulation/config.py @@ -13,21 +13,44 @@ from .api import Loan from .links import loan_links_factory from .permissions import views_permissions_factory -from .pidstore.pids import _LOANID_CONVERTER, CIRCULATION_LOAN_FETCHER, \ - CIRCULATION_LOAN_MINTER, CIRCULATION_LOAN_PID_TYPE +from .pidstore.pids import ( + _LOANID_CONVERTER, + CIRCULATION_LOAN_FETCHER, + CIRCULATION_LOAN_MINTER, + CIRCULATION_LOAN_PID_TYPE, +) from .search.api import LoansSearch -from .transitions.transitions import CreatedToPending, \ - ItemAtDeskToItemOnLoan, ItemInTransitHouseToItemReturned, \ - ItemOnLoanToItemInTransitHouse, ItemOnLoanToItemOnLoan, \ - ItemOnLoanToItemReturned, PendingToItemAtDesk, \ - PendingToItemInTransitPickup, ToCancelled, ToItemOnLoan -from .utils import can_be_requested, document_exists, document_ref_builder, \ - get_default_extension_duration, get_default_extension_max_count, \ - get_default_loan_duration, is_loan_duration_valid, item_can_circulate, \ - item_exists, item_location_retriever, item_ref_builder, patron_exists, \ - patron_ref_builder, same_location_validator, \ - transaction_location_validator, transaction_user_validator, \ - validate_item_pickup_transaction_locations +from .transitions.transitions import ( + CreatedToPending, + ItemAtDeskToItemOnLoan, + ItemInTransitHouseToItemReturned, + ItemOnLoanToItemInTransitHouse, + ItemOnLoanToItemOnLoan, + ItemOnLoanToItemReturned, + PendingToItemAtDesk, + PendingToItemInTransitPickup, + ToCancelled, + ToItemOnLoan, +) +from .utils import ( + can_be_requested, + document_exists, + document_ref_builder, + get_default_extension_duration, + get_default_extension_max_count, + get_default_loan_duration, + is_loan_duration_valid, + item_can_circulate, + item_exists, + item_location_retriever, + item_ref_builder, + patron_exists, + patron_ref_builder, + same_location_validator, + transaction_location_validator, + transaction_user_validator, + validate_item_pickup_transaction_locations, +) CIRCULATION_ITEMS_RETRIEVER_FROM_DOCUMENT = None """Function that returns a list of item PIDs given a Document PID.""" @@ -183,7 +206,6 @@ pid_minter=CIRCULATION_LOAN_MINTER, pid_fetcher=CIRCULATION_LOAN_FETCHER, search_class=LoansSearch, - search_type=None, record_class=Loan, record_loaders={ "application/json": ( diff --git a/invenio_circulation/ext.py b/invenio_circulation/ext.py index 2d76b84..4e25213 100644 --- a/invenio_circulation/ext.py +++ b/invenio_circulation/ext.py @@ -17,8 +17,11 @@ from . import config from .api import Loan -from .errors import InvalidLoanStateError, NoValidTransitionAvailableError, \ - TransitionConditionsFailedError +from .errors import ( + InvalidLoanStateError, + NoValidTransitionAvailableError, + TransitionConditionsFailedError, +) from .pidstore.pids import CIRCULATION_LOAN_PID_TYPE from .search.api import LoansSearch from .transitions.base import Transition diff --git a/invenio_circulation/records/loaders/schemas/json.py b/invenio_circulation/records/loaders/schemas/json.py index 7abd2a4..041f64c 100644 --- a/invenio_circulation/records/loaders/schemas/json.py +++ b/invenio_circulation/records/loaders/schemas/json.py @@ -46,7 +46,7 @@ def deserialize(self, value, attr=None, data=None, **kwargs): _value = super().deserialize(value, attr, data, **kwargs) # return the value as string after marshmallow validation # because Invenio does not support Python datetime JSON serializer yet - if _value and type(_value) == datetime: + if _value and isinstance(_value, datetime): return _value.isoformat() return _value @@ -60,7 +60,7 @@ def deserialize(self, value, attr=None, data=None, **kwargs): _value = super().deserialize(value, attr, data, **kwargs) # return the value as string after marshmallow validation # because Invenio does not support Python datetime JSON serializer yet - if _value and type(_value) == date: + if _value and isinstance(_value, date): return _value.isoformat() return _value diff --git a/invenio_circulation/transitions/base.py b/invenio_circulation/transitions/base.py index f60d8a6..4fa0459 100644 --- a/invenio_circulation/transitions/base.py +++ b/invenio_circulation/transitions/base.py @@ -16,10 +16,16 @@ from invenio_db import db from ..api import Loan, is_item_available_for_checkout -from ..errors import DocumentDoNotMatchError, DocumentNotAvailableError, \ - InvalidLoanStateError, InvalidPermissionError, ItemNotAvailableError, \ - MissingRequiredParameterError, TransitionConditionsFailedError, \ - TransitionConstraintsViolationError +from ..errors import ( + DocumentDoNotMatchError, + DocumentNotAvailableError, + InvalidLoanStateError, + InvalidPermissionError, + ItemNotAvailableError, + MissingRequiredParameterError, + TransitionConditionsFailedError, + TransitionConstraintsViolationError, +) from ..proxies import current_circulation from ..signals import loan_state_changed from ..utils import str2datetime diff --git a/invenio_circulation/transitions/transitions.py b/invenio_circulation/transitions/transitions.py index 094cc69..f14f0cb 100644 --- a/invenio_circulation/transitions/transitions.py +++ b/invenio_circulation/transitions/transitions.py @@ -13,12 +13,21 @@ from invenio_circulation.proxies import current_circulation -from ..api import can_be_requested, get_available_item_by_doc_pid, \ - get_document_pid_by_item_pid, get_pending_loans_by_doc_pid, \ - is_item_at_desk_available_for_checkout -from ..errors import ItemDoNotMatchError, ItemNotAvailableError, \ - LoanMaxExtensionError, RecordCannotBeRequestedError, \ - TransitionConditionsFailedError, TransitionConstraintsViolationError +from ..api import ( + can_be_requested, + get_available_item_by_doc_pid, + get_document_pid_by_item_pid, + get_pending_loans_by_doc_pid, + is_item_at_desk_available_for_checkout, +) +from ..errors import ( + ItemDoNotMatchError, + ItemNotAvailableError, + LoanMaxExtensionError, + RecordCannotBeRequestedError, + TransitionConditionsFailedError, + TransitionConstraintsViolationError, +) from ..transitions.base import Transition diff --git a/invenio_circulation/views.py b/invenio_circulation/views.py index 0ba5047..11dac22 100644 --- a/invenio_circulation/views.py +++ b/invenio_circulation/views.py @@ -16,8 +16,11 @@ from invenio_records_rest.views import pass_record from invenio_rest import ContentNegotiatedMethodView -from .errors import InvalidLoanStateError, ItemNotAvailableError, \ - MissingRequiredParameterError +from .errors import ( + InvalidLoanStateError, + ItemNotAvailableError, + MissingRequiredParameterError, +) from .permissions import need_permissions from .pidstore.pids import _LOANID_CONVERTER, CIRCULATION_LOAN_PID_TYPE from .proxies import current_circulation diff --git a/run-tests.sh b/run-tests.sh index 8de1a43..819097f 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -18,15 +18,37 @@ set -o errexit # Quit on unbound symbols set -o nounset -# Always bring down docker services -function cleanup() { +# Define function for bringing down services +function cleanup { eval "$(docker-services-cli down --env)" } -trap cleanup EXIT + +# Check for arguments +# Note: "-k" would clash with "pytest" +keep_services=0 +pytest_args=() +for arg in $@; do + # from the CLI args, filter out some known values and forward the rest to "pytest" + # note: we don't use "getopts" here b/c of some limitations (e.g. long options), + # which means that we can't combine short options (e.g. "./run-tests -Kk pattern") + case ${arg} in + -K|--keep-services) + keep_services=1 + ;; + *) + pytest_args+=( ${arg} ) + ;; + esac +done + +if [[ ${keep_services} -eq 0 ]]; then + trap cleanup EXIT +fi + python -m check_manifest --ignore ".*-requirements.txt" python -m sphinx.cmd.build -qnNW docs docs/_build/html -eval "$(docker-services-cli up --db ${DB:-postgresql} --search ${SEARCH:-elasticsearch} --cache ${CACHE:-redis} --env)" +eval "$(docker-services-cli up --db ${DB:-postgresql} --search ${SEARCH:-opensearch} --cache ${CACHE:-redis} --env)" python -m pytest tests_exit_code=$? python -m sphinx.cmd.build -qnNW -b doctest docs docs/_build/doctest diff --git a/setup.cfg b/setup.cfg index aaadc85..6f6a9af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,12 +96,6 @@ all_files = 1 [bdist_wheel] universal = 1 -[pydocstyle] -add_ignore = D401 - -[pycodestyle] -exclude = docs/conf.py - [compile_catalog] directory = invenio_circulation/translations/ @@ -123,10 +117,18 @@ output-dir = invenio_circulation/translations/ [isort] profile=black +[pydocstyle] +add_ignore = D401 + +[pycodestyle] +max-line-length = 88 +exclude = docs/conf.py + [check-manifest] ignore = *-requirements.txt [tool:pytest] -addopts = --black --isort --pydocstyle --doctest-glob="*.rst" --doctest-modules --cov=invenio_circulation --cov-report=term-missing -testpaths = tests invenio_circulation +addopts = --black --isort --pydocstyle --doctest-glob="*.rst" --doctest-modules --cov=invenio_administration --cov-report=term-missing +filterwarnings = ignore::pytest.PytestDeprecationWarning +testpaths = tests invenio_administration diff --git a/tests/conftest.py b/tests/conftest.py index d9f00b4..f42cf78 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,13 +27,25 @@ from invenio_circulation.pidstore.minters import loan_pid_minter from .helpers import create_loan, test_views_permissions_factory -from .utils import can_be_requested, document_exists, document_ref_builder, \ - get_default_extension_duration, get_default_extension_max_count, \ - get_default_loan_duration, is_loan_duration_valid, item_can_circulate, \ - item_exists, item_location_retriever, item_ref_builder, patron_exists, \ - patron_ref_builder, same_location_validator, \ - transaction_location_validator, transaction_user_validator, \ - validate_item_pickup_transaction_locations +from .utils import ( + can_be_requested, + document_exists, + document_ref_builder, + get_default_extension_duration, + get_default_extension_max_count, + get_default_loan_duration, + is_loan_duration_valid, + item_can_circulate, + item_exists, + item_location_retriever, + item_ref_builder, + patron_exists, + patron_ref_builder, + same_location_validator, + transaction_location_validator, + transaction_user_validator, + validate_item_pickup_transaction_locations, +) @pytest.fixture(scope="module") diff --git a/tests/test_errors.py b/tests/test_errors.py index 01970d2..682a96f 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -10,12 +10,19 @@ import pytest -from invenio_circulation.errors import InvalidLoanStateError, \ - InvalidPermissionError, ItemNotAvailableError, LoanMaxExtensionError, \ - MissingRequiredParameterError, MultipleLoansOnItemError, \ - NotImplementedConfigurationError, NoValidTransitionAvailableError, \ - RecordCannotBeRequestedError, TransitionConditionsFailedError, \ - TransitionConstraintsViolationError +from invenio_circulation.errors import ( + InvalidLoanStateError, + InvalidPermissionError, + ItemNotAvailableError, + LoanMaxExtensionError, + MissingRequiredParameterError, + MultipleLoansOnItemError, + NotImplementedConfigurationError, + NoValidTransitionAvailableError, + RecordCannotBeRequestedError, + TransitionConditionsFailedError, + TransitionConstraintsViolationError, +) def test_not_implemented(app): diff --git a/tests/test_loan_base_constraints.py b/tests/test_loan_base_constraints.py index a1a116c..a763a58 100644 --- a/tests/test_loan_base_constraints.py +++ b/tests/test_loan_base_constraints.py @@ -11,9 +11,12 @@ import arrow import pytest -from invenio_circulation.errors import ItemDoNotMatchError, \ - ItemNotAvailableError, MissingRequiredParameterError, \ - TransitionConstraintsViolationError +from invenio_circulation.errors import ( + ItemDoNotMatchError, + ItemNotAvailableError, + MissingRequiredParameterError, + TransitionConstraintsViolationError, +) from invenio_circulation.pidstore.fetchers import loan_pid_fetcher from invenio_circulation.proxies import current_circulation diff --git a/tests/test_loan_search.py b/tests/test_loan_search.py index 6561ebd..bb8e786 100644 --- a/tests/test_loan_search.py +++ b/tests/test_loan_search.py @@ -9,8 +9,11 @@ """Tests for loan search class.""" from invenio_circulation.api import Loan -from invenio_circulation.search.api import search_by_patron_item_or_document, \ - search_by_patron_pid, search_by_pid +from invenio_circulation.search.api import ( + search_by_patron_item_or_document, + search_by_patron_pid, + search_by_pid, +) def _assert_total(total, expected): diff --git a/tests/test_loan_transition_pending_to_item_at_desk_or_transit.py b/tests/test_loan_transition_pending_to_item_at_desk_or_transit.py index 36a08f4..3cf7757 100644 --- a/tests/test_loan_transition_pending_to_item_at_desk_or_transit.py +++ b/tests/test_loan_transition_pending_to_item_at_desk_or_transit.py @@ -10,11 +10,12 @@ import pytest -from invenio_circulation.errors import NotImplementedConfigurationError, \ - NoValidTransitionAvailableError +from invenio_circulation.errors import ( + NotImplementedConfigurationError, + NoValidTransitionAvailableError, +) from invenio_circulation.proxies import current_circulation -from invenio_circulation.utils import \ - validate_item_pickup_transaction_locations +from invenio_circulation.utils import validate_item_pickup_transaction_locations from .helpers import SwappedConfig diff --git a/tests/test_loan_transition_to_item_on_loan.py b/tests/test_loan_transition_to_item_on_loan.py index 521f912..76764ba 100644 --- a/tests/test_loan_transition_to_item_on_loan.py +++ b/tests/test_loan_transition_to_item_on_loan.py @@ -13,8 +13,10 @@ import arrow import pytest -from invenio_circulation.errors import ItemNotAvailableError, \ - TransitionConstraintsViolationError +from invenio_circulation.errors import ( + ItemNotAvailableError, + TransitionConstraintsViolationError, +) from invenio_circulation.proxies import current_circulation from .helpers import SwappedConfig diff --git a/tests/test_loan_transitions.py b/tests/test_loan_transitions.py index 96cac4f..578f1bb 100644 --- a/tests/test_loan_transitions.py +++ b/tests/test_loan_transitions.py @@ -15,11 +15,18 @@ import pytest from flask_security import login_user -from invenio_circulation.api import get_loan_for_item, \ - is_item_at_desk_available_for_checkout, is_item_available_for_checkout -from invenio_circulation.errors import ItemDoNotMatchError, \ - LoanMaxExtensionError, NoValidTransitionAvailableError, \ - RecordCannotBeRequestedError, TransitionConstraintsViolationError +from invenio_circulation.api import ( + get_loan_for_item, + is_item_at_desk_available_for_checkout, + is_item_available_for_checkout, +) +from invenio_circulation.errors import ( + ItemDoNotMatchError, + LoanMaxExtensionError, + NoValidTransitionAvailableError, + RecordCannotBeRequestedError, + TransitionConstraintsViolationError, +) from invenio_circulation.proxies import current_circulation from invenio_circulation.utils import str2datetime