From 671152a57ac120509b39aba135d4585c84cd3523 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Fri, 15 Dec 2023 13:59:22 +0100 Subject: [PATCH 01/10] Working on RDM 12 compatibility --- .github/workflows/build.yaml | 75 ++++++++++++++++++++++++++++ .github/workflows/main.yaml | 92 ----------------------------------- .github/workflows/manual.yaml | 15 ++++++ .github/workflows/push.yaml | 41 ++++++++++++++++ run_tests.sh => run-tests.sh | 5 +- 5 files changed, 133 insertions(+), 95 deletions(-) create mode 100644 .github/workflows/build.yaml delete mode 100644 .github/workflows/main.yaml create mode 100644 .github/workflows/manual.yaml create mode 100644 .github/workflows/push.yaml rename run_tests.sh => run-tests.sh (85%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..1d5edf8a --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,75 @@ +name: Build and test + +on: + workflow_call: + inputs: + oarepo: + description: OARepo version (11, 12, ...) + required: true + default: 11 + type: string + +env: + OAREPO_VERSION: ${{ inputs.oarepo }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.10" + - name: Cache pip + uses: actions/cache@v3 + with: + # This path is specific to Ubuntu + path: ~/.cache/pip + # Look to see if there is a cache hit for the corresponding requirements file + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + ${{ runner.os }}- + + - name: Configure sysctl limits + run: | + sudo swapoff -a + sudo sysctl -w vm.swappiness=1 + sudo sysctl -w fs.file-max=262144 + sudo sysctl -w vm.max_map_count=262144 + + - name: Runs Opensearch + uses: ankane/setup-opensearch@v1 + with: + plugins: analysis-icu + + - name: Start Redis + uses: supercharge/redis-github-action@1.7.0 + with: + redis-version: ${{ matrix.redis-version }} + + - name: Run tests + run: | + ./run-tests.sh + + - name: Build package to publish + run: | + .venv-builder/bin/python setup.py sdist bdist_wheel + + - name: Freeze packages + run: | + .venv-builder/bin/pip freeze > requirements.txt + .venv-tests/bin/pip freeze >>requirements.txt + + - name: Archive production artifacts + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist + + - name: Archive production artifacts + uses: actions/upload-artifact@v3 + with: + name: requirements.txt + path: requirements.txt diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml deleted file mode 100644 index 7d7482ac..00000000 --- a/.github/workflows/main.yaml +++ /dev/null @@ -1,92 +0,0 @@ -name: Test python - -on: [ push ] - -jobs: - build: - runs-on: ubuntu-latest - services: - redis: - # Docker Hub image - image: redis - # Set health checks to wait until redis has started - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 - strategy: - matrix: - python-version: [ "3.9", "3.10" ] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Cache pip - uses: actions/cache@v3 - with: - # This path is specific to Ubuntu - path: ~/.cache/pip - # Look to see if there is a cache hit for the corresponding requirements file - key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - ${{ runner.os }}- - - - name: Configure sysctl limits - run: | - sudo swapoff -a - sudo sysctl -w vm.swappiness=1 - sudo sysctl -w fs.file-max=262144 - sudo sysctl -w vm.max_map_count=262144 - - - name: Runs Opensearch - uses: ankane/setup-opensearch@v1 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip wheel setuptools - pip install -e '.[tests]' - pip list - - - name: Test with pytest - run: | - ./run_tests.sh - - - - name: Build package to publish - run: | - python setup.py sdist bdist_wheel - - - name: Archive production artifacts - uses: actions/upload-artifact@v3 - with: - name: dist - path: dist - - deploy: - runs-on: ubuntu-latest - needs: build - steps: - - name: Use built artifacts - uses: actions/download-artifact@v3 - with: - name: dist - path: dist - - - name: List files - run: | - ls -la - ls -la dist - - - name: Publish package - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1 - with: - skip_existing: true - user: __token__ - password: ${{ secrets.PYPI_PASSWORD }} diff --git a/.github/workflows/manual.yaml b/.github/workflows/manual.yaml new file mode 100644 index 00000000..e05df2cf --- /dev/null +++ b/.github/workflows/manual.yaml @@ -0,0 +1,15 @@ +name: Dispatch + +on: + workflow_dispatch: + inputs: + oarepo: + description: OARepo version (11, 12, ...) + required: true + default: 11 + +jobs: + build: + uses: ./.github/workflows/build.yaml + with: + oarepo: ${{ github.event.inputs.oarepo }} diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml new file mode 100644 index 00000000..54317498 --- /dev/null +++ b/.github/workflows/push.yaml @@ -0,0 +1,41 @@ +name: Build, test and publish + +on: push + +permissions: + id-token: write + contents: read + +jobs: + build11: + uses: ./.github/workflows/build.yaml + with: + oarepo: 11 + + build12: + uses: ./.github/workflows/build.yaml + with: + oarepo: 12 + + publish: + runs-on: ubuntu-latest + needs: build11 + steps: + - name: Use built artifacts + uses: actions/download-artifact@v3 + with: + name: dist + path: dist + + - name: List files + run: | + ls -la + ls -la dist + + - name: Publish package + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip_existing: true + user: __token__ + password: ${{ secrets.PYPI_PASSWORD }} diff --git a/run_tests.sh b/run-tests.sh similarity index 85% rename from run_tests.sh rename to run-tests.sh index 85f582ce..4567055c 100755 --- a/run_tests.sh +++ b/run-tests.sh @@ -2,7 +2,6 @@ set -e OAREPO_VERSION=${OAREPO_VERSION:-11} -OAREPO_VERSION_MAX=$((OAREPO_VERSION+1)) MODEL="thesis" @@ -33,8 +32,8 @@ fi python3 -m venv $MODEL_VENV . $MODEL_VENV/bin/activate pip install -U setuptools pip wheel -pip install "oarepo>=$OAREPO_VERSION,<$OAREPO_VERSION_MAX" -pip install "./$BUILD_TEST_DIR/$MODEL[tests]" +pip install "oarepo[tests]==$OAREPO_VERSION.*" +pip install "./$BUILD_TEST_DIR/${MODEL}[tests]" pip install . pip install oarepo-ui From d3a1851ee65c748bddf150d013d5a60e05e8aa73 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Fri, 15 Dec 2023 16:06:12 +0100 Subject: [PATCH 02/10] working on tests - UI tests are broken even on RDM 11 --- .gitignore | 4 +++- oarepo_requests/components/requests.py | 28 +++++++++++++++----------- run-tests.sh | 8 ++++---- setup.cfg | 8 +++++++- tests/__init__.py | 0 5 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 tests/__init__.py diff --git a/.gitignore b/.gitignore index ad71df36..0287eb89 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,7 @@ target/ tests/test.db -.venv +.venv* .direnv docs/migration/data @@ -89,3 +89,5 @@ dist/ .model_venv/ .vscode + +thesis diff --git a/oarepo_requests/components/requests.py b/oarepo_requests/components/requests.py index f2a415c2..9279c25d 100644 --- a/oarepo_requests/components/requests.py +++ b/oarepo_requests/components/requests.py @@ -25,16 +25,22 @@ def roles(self, **kwargs): class AllowedRequestsComponent(ServiceComponent): """Service component which sets all data in the record.""" - def _add_available_requests(self, identity, record, dict_to_save_result, **kwargs): + def _add_available_requests(self, identity, data, dict_to_save_result, **kwargs): # todo discriminate requests from other stuff which can be on parent in the future # todo what to throw if parent doesn't exist - parent_copy = copy.deepcopy(record["parent"]) + + available_requests = {} + kwargs[dict_to_save_result]["allowed_requests"] = available_requests + + if not data: + # not authorized or any other error + return + parent_copy = copy.deepcopy(data["parent"]) requests = { k: v for k, v in parent_copy.items() if isinstance(v, dict) and "receiver" in v } # todo more sensible request identification - available_requests = {} for request_name, request_dict in requests.items(): request = current_requests_service.record_cls.get_record(request_dict["id"]) @@ -54,19 +60,17 @@ def _add_available_requests(self, identity, record, dict_to_save_result, **kwarg saved_request_data["actions"] = [action_name] available_requests[request_name] = saved_request_data else: - saved_request_data["actions"].append(action_name) + saved_request_data["actions"].append(action_name) # noqa we are sure that saved_request_data exists - dict_to_save_result = kwargs[dict_to_save_result] - dict_to_save_result["allowed_requests"] = available_requests - def before_ui_detail(self, identity, data=None, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "extra_context", **kwargs) + def before_ui_detail(self, identity, data=None, errors=None, **kwargs): + self._add_available_requests(identity, data, "extra_context", **kwargs) - def before_ui_edit(self, identity, data=None, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "extra_context", **kwargs) + def before_ui_edit(self, identity, data=None, errors=None, **kwargs): + self._add_available_requests(identity, data, "extra_context", **kwargs) - def form_config(self, identity, data=None, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "form_config", **kwargs) + def form_config(self, identity, data=None, errors=None, **kwargs): + self._add_available_requests(identity, data, "form_config", **kwargs) class PublishDraftComponentPrivate(ServiceComponent): diff --git a/run-tests.sh b/run-tests.sh index 4567055c..772b3273 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -18,11 +18,11 @@ python3 -m venv $BUILDER_VENV pip install -U setuptools pip wheel pip install -U oarepo-model-builder-tests oarepo-model-builder-requests oarepo-model-builder-drafts -if test -d $BUILD_TEST_DIR/$MODEL; then +if test -d $MODEL; then rm -rf $MODEL fi -oarepo-compile-model ./$CODE_TEST_DIR/$MODEL.yaml --output-directory ./$BUILD_TEST_DIR/$MODEL -vvv +oarepo-compile-model ./$CODE_TEST_DIR/$MODEL.yaml --output-directory $MODEL -vvv MODEL_VENV=".venv-tests" @@ -33,9 +33,9 @@ python3 -m venv $MODEL_VENV . $MODEL_VENV/bin/activate pip install -U setuptools pip wheel pip install "oarepo[tests]==$OAREPO_VERSION.*" -pip install "./$BUILD_TEST_DIR/${MODEL}[tests]" -pip install . +pip install -e "./${MODEL}" pip install oarepo-ui +pip install -e . pytest $BUILD_TEST_DIR/test_requests pytest $BUILD_TEST_DIR/test_ui \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index f2f66b91..20db76d5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,11 +12,17 @@ long_description_content_type = text/markdown python = >=3.9 install_requires = invenio-requests -#packages = find: + +packages = find: + +[tool.setuptools.packages.find] +include = ['oarepo_requests.*'] [options.package_data] * = *.json, *.rst, *.md, *.json5, *.jinja2 + + [options.extras_require] tests = oarepo-model-builder-tests diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b From 6f9931b6d24ae2957b543cf05c107cd1117e86b9 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Fri, 15 Dec 2023 16:17:13 +0100 Subject: [PATCH 03/10] Adding manifest --- MANIFEST.in | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..b8023fe7 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-include oarepo_requests * +prune tests +prune thesis \ No newline at end of file From 2cd2b8e9ba7ef77cdc486f5cac66806046f51b01 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sat, 16 Dec 2023 10:47:57 +0100 Subject: [PATCH 04/10] making ui components api consistent --- oarepo_requests/components/__init__.py | 6 - oarepo_requests/components/requests.py | 130 ------------------ oarepo_requests/resources/__init__.py | 0 .../resources/components/__init__.py | 56 ++++++++ oarepo_requests/services/__init__.py | 0 .../services/components/__init__.py | 63 +++++++++ tests/test_ui/model.py | 10 +- tests/thesis.yaml | 2 +- 8 files changed, 124 insertions(+), 143 deletions(-) delete mode 100644 oarepo_requests/components/__init__.py delete mode 100644 oarepo_requests/components/requests.py create mode 100644 oarepo_requests/resources/__init__.py create mode 100644 oarepo_requests/resources/components/__init__.py create mode 100644 oarepo_requests/services/__init__.py create mode 100644 oarepo_requests/services/components/__init__.py diff --git a/oarepo_requests/components/__init__.py b/oarepo_requests/components/__init__.py deleted file mode 100644 index 7cfd1456..00000000 --- a/oarepo_requests/components/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .requests import AllowedRequestsComponent, PublishDraftComponent - -__all__ = [ - "AllowedRequestsComponent", - "PublishDraftComponent", -] diff --git a/oarepo_requests/components/requests.py b/oarepo_requests/components/requests.py deleted file mode 100644 index 9279c25d..00000000 --- a/oarepo_requests/components/requests.py +++ /dev/null @@ -1,130 +0,0 @@ -import copy -import functools - -from invenio_records_resources.services.errors import PermissionDeniedError -from invenio_records_resources.services.records.components import ServiceComponent -from invenio_records_resources.services.uow import RecordCommitOp -from invenio_requests.customizations import LogEventType, RequestActions -from invenio_requests.proxies import ( - current_events_service, - current_request_type_registry, - current_requests_service, -) - -""" -class RecordCommunitiesAction(CommunityRoles): - - def __init__(self, action): - self._action = action - - def roles(self, **kwargs): - return {r.name for r in current_roles.can(self._action)} -""" - - -class AllowedRequestsComponent(ServiceComponent): - """Service component which sets all data in the record.""" - - def _add_available_requests(self, identity, data, dict_to_save_result, **kwargs): - # todo discriminate requests from other stuff which can be on parent in the future - # todo what to throw if parent doesn't exist - - available_requests = {} - kwargs[dict_to_save_result]["allowed_requests"] = available_requests - - if not data: - # not authorized or any other error - return - parent_copy = copy.deepcopy(data["parent"]) - requests = { - k: v - for k, v in parent_copy.items() - if isinstance(v, dict) and "receiver" in v - } # todo more sensible request identification - - for request_name, request_dict in requests.items(): - request = current_requests_service.record_cls.get_record(request_dict["id"]) - request_type = current_request_type_registry.lookup(request_dict["type"]) - for action_name, action in request_type.available_actions.items(): - try: - current_requests_service.require_permission( - identity, f"action_{action_name}", request=request - ) - except PermissionDeniedError: - continue - action = RequestActions.get_action(request, action_name) - if not action.can_execute(): - continue - if request_name not in available_requests: - saved_request_data = copy.deepcopy(request_dict) - saved_request_data["actions"] = [action_name] - available_requests[request_name] = saved_request_data - else: - saved_request_data["actions"].append(action_name) # noqa we are sure that saved_request_data exists - - - def before_ui_detail(self, identity, data=None, errors=None, **kwargs): - self._add_available_requests(identity, data, "extra_context", **kwargs) - - def before_ui_edit(self, identity, data=None, errors=None, **kwargs): - self._add_available_requests(identity, data, "extra_context", **kwargs) - - def form_config(self, identity, data=None, errors=None, **kwargs): - self._add_available_requests(identity, data, "form_config", **kwargs) - - -class PublishDraftComponentPrivate(ServiceComponent): - """Service component for request integration.""" - - def __init__(self, publish_request_type, delete_request_type, *args, **kwargs): - super().__init__(*args, **kwargs) - self.publish_request_type = publish_request_type - self.delete_request_type = delete_request_type - - def create(self, identity, data=None, record=None, **kwargs): - """Create the review if requested.""" - # topic and request_type in kwargs - if self.publish_request_type: - type_ = current_request_type_registry.lookup( - self.publish_request_type, quiet=True - ) - request_item = current_requests_service.create( - identity, {}, type_, receiver=None, topic=record, uow=self.uow - ) - setattr(record.parent, self.publish_request_type, request_item._request) - self.uow.register(RecordCommitOp(record.parent)) - - def publish(self, identity, data=None, record=None, **kwargs): - publish_request = getattr(record.parent, self.publish_request_type) - - if publish_request is not None: - request = publish_request.get_object() - request_status = "accepted" - request.status = request_status - setattr(record.parent, self.publish_request_type, None) - event = LogEventType( - payload={ - "event": request_status, - "content": "record was published through direct call without request", - } - ) - _data = dict(payload=event.payload) - current_events_service.create( - identity, request.id, _data, event, uow=self.uow - ) - - if self.delete_request_type: - type_ = current_request_type_registry.lookup( - self.delete_request_type, quiet=True - ) - request_item = current_requests_service.create( - identity, {}, type_, receiver=None, topic=record, uow=self.uow - ) - setattr(record.parent, self.delete_request_type, request_item._request) - self.uow.register(RecordCommitOp(record.parent)) - - -def PublishDraftComponent(publish_request_type, delete_request_type): - return functools.partial( - PublishDraftComponentPrivate, publish_request_type, delete_request_type - ) diff --git a/oarepo_requests/resources/__init__.py b/oarepo_requests/resources/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/oarepo_requests/resources/components/__init__.py b/oarepo_requests/resources/components/__init__.py new file mode 100644 index 00000000..73531526 --- /dev/null +++ b/oarepo_requests/resources/components/__init__.py @@ -0,0 +1,56 @@ +import copy + +from invenio_records_resources.services.errors import PermissionDeniedError +from invenio_requests import current_requests_service, current_request_type_registry +from invenio_requests.customizations import RequestActions + + +class AllowedRequestsComponent(UIResourceComponent): + """Service component which sets all data in the record.""" + + def _add_available_requests(self, identity, record, dict_to_save_result, kwargs): + # todo discriminate requests from other stuff which can be on parent in the future + # todo what to throw if parent doesn't exist + + if not record: + return + + available_requests = {} + kwargs[dict_to_save_result]["allowed_requests"] = available_requests + + parent_copy = copy.deepcopy(record.data["parent"]) + requests = { + k: v + for k, v in parent_copy.items() + if isinstance(v, dict) and "receiver" in v + } # todo more sensible request identification + + for request_name, request_dict in requests.items(): + request = current_requests_service.record_cls.get_record(request_dict["id"]) + request_type = current_request_type_registry.lookup(request_dict["type"]) + for action_name, action in request_type.available_actions.items(): + try: + current_requests_service.require_permission( + identity, f"action_{action_name}", request=request + ) + except PermissionDeniedError: + continue + action = RequestActions.get_action(request, action_name) + if not action.can_execute(): + continue + if request_name not in available_requests: + saved_request_data = copy.deepcopy(request_dict) + saved_request_data["actions"] = [action_name] + available_requests[request_name] = saved_request_data + else: + saved_request_data["actions"].append(action_name) # noqa we are sure that saved_request_data exists + + + def before_ui_detail(self, identity, record=None, errors=None, **kwargs): + self._add_available_requests(identity, record, "extra_context", kwargs) + + def before_ui_edit(self, identity, record=None, errors=None, **kwargs): + self._add_available_requests(identity, record, "extra_context", kwargs) + + def form_config(self, identity, record=None, errors=None, **kwargs): + self._add_available_requests(identity, record, "form_config", kwargs) diff --git a/oarepo_requests/services/__init__.py b/oarepo_requests/services/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/oarepo_requests/services/components/__init__.py b/oarepo_requests/services/components/__init__.py new file mode 100644 index 00000000..522fef9f --- /dev/null +++ b/oarepo_requests/services/components/__init__.py @@ -0,0 +1,63 @@ +import functools + +from invenio_records_resources.services.records.components import ServiceComponent +from invenio_records_resources.services.uow import RecordCommitOp +from invenio_requests import current_request_type_registry, current_requests_service, current_events_service +from invenio_requests.customizations import LogEventType + + +class PublishDraftComponentPrivate(ServiceComponent): + """Service component for request integration.""" + + def __init__(self, publish_request_type, delete_request_type, *args, **kwargs): + super().__init__(*args, **kwargs) + self.publish_request_type = publish_request_type + self.delete_request_type = delete_request_type + + def create(self, identity, data=None, record=None, **kwargs): + """Create the review if requested.""" + # topic and request_type in kwargs + if self.publish_request_type: + type_ = current_request_type_registry.lookup( + self.publish_request_type, quiet=True + ) + request_item = current_requests_service.create( + identity, {}, type_, receiver=None, topic=record, uow=self.uow + ) + setattr(record.parent, self.publish_request_type, request_item._request) + self.uow.register(RecordCommitOp(record.parent)) + + def publish(self, identity, data=None, record=None, **kwargs): + publish_request = getattr(record.parent, self.publish_request_type) + + if publish_request is not None: + request = publish_request.get_object() + request_status = "accepted" + request.status = request_status + setattr(record.parent, self.publish_request_type, None) + event = LogEventType( + payload={ + "event": request_status, + "content": "record was published through direct call without request", + } + ) + _data = dict(payload=event.payload) + current_events_service.create( + identity, request.id, _data, event, uow=self.uow + ) + + if self.delete_request_type: + type_ = current_request_type_registry.lookup( + self.delete_request_type, quiet=True + ) + request_item = current_requests_service.create( + identity, {}, type_, receiver=None, topic=record, uow=self.uow + ) + setattr(record.parent, self.delete_request_type, request_item._request) + self.uow.register(RecordCommitOp(record.parent)) + + +def PublishDraftComponent(publish_request_type, delete_request_type): + return functools.partial( + PublishDraftComponentPrivate, publish_request_type, delete_request_type + ) diff --git a/tests/test_ui/model.py b/tests/test_ui/model.py index 56d5ab5f..0e2da275 100644 --- a/tests/test_ui/model.py +++ b/tests/test_ui/model.py @@ -6,7 +6,7 @@ from oarepo_ui.resources.components import PermissionsComponent from thesis.resources.records.ui import ThesisUIJSONSerializer -from oarepo_requests.components import AllowedRequestsComponent +from oarepo_requests.resources.components import AllowedRequestsComponent class ModelUIResourceConfig(RecordsUIResourceConfig): @@ -20,11 +20,9 @@ class ModelUIResourceConfig(RecordsUIResourceConfig): templates = { **RecordsUIResourceConfig.templates, - "detail": {"layout": "TestDetail.jinja", "blocks": {}}, - "search": { - "layout": "TestDetail.jinja", - }, - "edit": {"layout": "TestEdit.jinja"}, + "detail": "TestDetail", + "search": "TestDetail", + "edit": "TestEdit", } components = [BabelComponent, PermissionsComponent, AllowedRequestsComponent] diff --git a/tests/thesis.yaml b/tests/thesis.yaml index 5143a910..e08ea8ae 100644 --- a/tests/thesis.yaml +++ b/tests/thesis.yaml @@ -9,7 +9,7 @@ record: components: - PublishDraftComponent("publish_draft", "delete_record") imports: - - import: oarepo_requests.components.requests.PublishDraftComponent + - import: oarepo_requests.services.components.PublishDraftComponent draft: requests: publish-draft: From 53ba03004bf7b62e29cd75f53248c1085a74b3a0 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 11:05:49 +0100 Subject: [PATCH 05/10] Up to date with oarepo-ui changes --- oarepo_requests/resources/components/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/oarepo_requests/resources/components/__init__.py b/oarepo_requests/resources/components/__init__.py index 73531526..269e2e40 100644 --- a/oarepo_requests/resources/components/__init__.py +++ b/oarepo_requests/resources/components/__init__.py @@ -3,6 +3,7 @@ from invenio_records_resources.services.errors import PermissionDeniedError from invenio_requests import current_requests_service, current_request_type_registry from invenio_requests.customizations import RequestActions +from oarepo_ui.resources.components import UIResourceComponent class AllowedRequestsComponent(UIResourceComponent): @@ -46,11 +47,11 @@ def _add_available_requests(self, identity, record, dict_to_save_result, kwargs) saved_request_data["actions"].append(action_name) # noqa we are sure that saved_request_data exists - def before_ui_detail(self, identity, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "extra_context", kwargs) + def before_ui_detail(self, identity, api_record=None, errors=None, **kwargs): + self._add_available_requests(identity, api_record, "extra_context", kwargs) - def before_ui_edit(self, identity, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "extra_context", kwargs) + def before_ui_edit(self, identity, api_record=None, errors=None, **kwargs): + self._add_available_requests(identity, api_record, "extra_context", kwargs) - def form_config(self, identity, record=None, errors=None, **kwargs): - self._add_available_requests(identity, record, "form_config", kwargs) + def form_config(self, identity, api_record=None, errors=None, **kwargs): + self._add_available_requests(identity, api_record, "form_config", kwargs) From 6091408565c3ff0d2b2c8266e61e63e9c6363974 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 17:17:55 +0100 Subject: [PATCH 06/10] Fixing tests --- tests/test_requests/test_requests.py | 12 +++++++++-- tests/test_ui/templates/TestDetail.jinja | 10 +++++++-- tests/test_ui/templates/TestEdit.jinja | 27 ++++++++++++++++++------ tests/test_ui/test_ui_resource.py | 21 ++++++++++-------- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/tests/test_requests/test_requests.py b/tests/test_requests/test_requests.py index 86ce77b4..5b8f29cf 100644 --- a/tests/test_requests/test_requests.py +++ b/tests/test_requests/test_requests.py @@ -1,5 +1,5 @@ import pytest -from invenio_pidstore.errors import PIDDeletedError, PIDUnregistered +from invenio_pidstore.errors import PIDDeletedError, PIDUnregistered, PIDDoesNotExistError from invenio_records_resources.services.errors import PermissionDeniedError from sqlalchemy.orm.exc import NoResultFound @@ -20,8 +20,16 @@ def test_workflow( identity_simple, resp1._obj.parent.publish_draft.id, "submit" ) - with pytest.raises(NoResultFound): + try: record_service.read_draft(identity_simple, record_id) + raise Exception("Expecting PIDDoesNotExistError for RDM 12 or NoResultFound for RDM 11") + except PIDDoesNotExistError: + # RDM 12 error + pass + except NoResultFound: + # RDM 11 error + pass + resp2 = record_service.read(identity_simple, record_id) assert resp2._obj.parent.publish_draft is None diff --git a/tests/test_ui/templates/TestDetail.jinja b/tests/test_ui/templates/TestDetail.jinja index a355fa0b..8f3c5efb 100644 --- a/tests/test_ui/templates/TestDetail.jinja +++ b/tests/test_ui/templates/TestDetail.jinja @@ -1,5 +1,11 @@ {#def extra_context #} -available_requests= +{ {% for request_name, request in extra_context.allowed_requests.items() %} -{{ request_name }}: {{ request }} + "{{ request_name }}": { + "type": {{ request.type|tojson|safe }}, + "status": {{ request.status|tojson|safe }}, + "receiver": {{ request.receiver|tojson|safe }}, + "actions": {{ request.actions|tojson|safe }} + } {% endfor %} +} diff --git a/tests/test_ui/templates/TestEdit.jinja b/tests/test_ui/templates/TestEdit.jinja index 8bcd6b6b..12ee3504 100644 --- a/tests/test_ui/templates/TestEdit.jinja +++ b/tests/test_ui/templates/TestEdit.jinja @@ -1,11 +1,26 @@ {#def form_config, extra_context #} -available_requests= +{ +"available_requests": +{ {% for request_name, request in extra_context.allowed_requests.items() %} -{{ request_name }}: {{ request }} + "{{ request_name }}": { + "type": {{ request.type|tojson|safe }}, + "status": {{ request.status|tojson|safe }}, + "receiver": {{ request.receiver|tojson|safe }}, + "actions": {{ request.actions|tojson|safe }} + } {% endfor %} -{% if form_config %} -allowed requests in form config: +}, + +"form_config": +{ {% for request_name, request in form_config["allowed_requests"].items() %} -{{ request_name }}: {{ request }} + "{{ request_name }}": { + "type": {{ request.type|tojson|safe }}, + "status": {{ request.status|tojson|safe }}, + "receiver": {{ request.receiver|tojson|safe }}, + "actions": {{ request.actions|tojson|safe }} + } {% endfor %} -{% endif %} \ No newline at end of file +} +} \ No newline at end of file diff --git a/tests/test_ui/test_ui_resource.py b/tests/test_ui/test_ui_resource.py index df3ffaef..b5af1134 100644 --- a/tests/test_ui/test_ui_resource.py +++ b/tests/test_ui/test_ui_resource.py @@ -1,3 +1,6 @@ +import json + + def test_draft_publish_request_present( app, record_ui_resource, example_topic_draft, client_with_login, fake_manifest ): @@ -10,9 +13,9 @@ def check_request(ctext): with client_with_login.get(f"/thesis/{example_topic_draft['id']}/edit") as c: assert c.status_code == 200 - base_part, form_part = c.text.split("allowed requests in form config:") - check_request(base_part) - check_request(form_part) + data = json.loads(c.text) + assert data["available_requests"]["publish_draft"] == {'actions': ['submit', 'delete'], 'receiver': None, 'status': 'created', 'type': 'publish_draft'} + assert data["form_config"]["publish_draft"] == {'actions': ['submit', 'delete'], 'receiver': None, 'status': 'created', 'type': 'publish_draft'} def test_draft_publish_unauthorized( @@ -28,12 +31,12 @@ def test_record_delete_request_present( ): with client_with_login.get(f"/thesis/{example_topic['id']}") as c: assert c.status_code == 200 - assert "delete_record: " in c.text - assert "'type': 'delete_record'" in c.text - assert "'receiver': None" in c.text - assert "'status': 'created'" in c.text - assert "'links': {}" in c.text - assert "'actions': ['submit']" in c.text + data = json.loads(c.text) + assert "delete_record" in data + assert data["delete_record"]['type'] == "delete_record" + assert data["delete_record"]["receiver"] is None + assert data["delete_record"]["status"] == "created" + assert data["delete_record"]["actions"] == ["submit", "delete"] def test_record_delete_unauthorized( From 1facf1c15505467fc86df34721db836be2972ca1 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 17:48:11 +0100 Subject: [PATCH 07/10] Fixing tests --- tests/test_ui/test_ui_resource.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_ui/test_ui_resource.py b/tests/test_ui/test_ui_resource.py index b5af1134..47b38ae5 100644 --- a/tests/test_ui/test_ui_resource.py +++ b/tests/test_ui/test_ui_resource.py @@ -1,4 +1,9 @@ import json +from oarepo import __version__ as oarepo_version +is_oarepo_11 = oarepo_version.split(".")[0] == "11" + +# RDM 12 adds "delete" to allowed actions (to be able to delete the request) +allowed_actions = ["submit"] if is_oarepo_11 else ["submit", "delete"] def test_draft_publish_request_present( @@ -14,7 +19,7 @@ def check_request(ctext): with client_with_login.get(f"/thesis/{example_topic_draft['id']}/edit") as c: assert c.status_code == 200 data = json.loads(c.text) - assert data["available_requests"]["publish_draft"] == {'actions': ['submit', 'delete'], 'receiver': None, 'status': 'created', 'type': 'publish_draft'} + assert data["available_requests"]["publish_draft"] == {'actions': allowed_actions, 'receiver': None, 'status': 'created', 'type': 'publish_draft'} assert data["form_config"]["publish_draft"] == {'actions': ['submit', 'delete'], 'receiver': None, 'status': 'created', 'type': 'publish_draft'} @@ -36,7 +41,7 @@ def test_record_delete_request_present( assert data["delete_record"]['type'] == "delete_record" assert data["delete_record"]["receiver"] is None assert data["delete_record"]["status"] == "created" - assert data["delete_record"]["actions"] == ["submit", "delete"] + assert data["delete_record"]["actions"] == allowed_actions def test_record_delete_unauthorized( From 1995282263033f6883e508b8289ddec55abf5800 Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 17:55:35 +0100 Subject: [PATCH 08/10] Fixed tests --- tests/test_ui/test_ui_resource.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/test_ui/test_ui_resource.py b/tests/test_ui/test_ui_resource.py index 47b38ae5..a27e1843 100644 --- a/tests/test_ui/test_ui_resource.py +++ b/tests/test_ui/test_ui_resource.py @@ -9,18 +9,11 @@ def test_draft_publish_request_present( app, record_ui_resource, example_topic_draft, client_with_login, fake_manifest ): - def check_request(ctext): - assert "publish_draft:" in ctext - assert "type': 'publish_draft'" in ctext - assert "'status': 'created'" in ctext - assert "'receiver': None" in ctext - assert "'actions': ['submit']" in ctext - with client_with_login.get(f"/thesis/{example_topic_draft['id']}/edit") as c: assert c.status_code == 200 data = json.loads(c.text) assert data["available_requests"]["publish_draft"] == {'actions': allowed_actions, 'receiver': None, 'status': 'created', 'type': 'publish_draft'} - assert data["form_config"]["publish_draft"] == {'actions': ['submit', 'delete'], 'receiver': None, 'status': 'created', 'type': 'publish_draft'} + assert data["form_config"]["publish_draft"] == {'actions': allowed_actions, 'receiver': None, 'status': 'created', 'type': 'publish_draft'} def test_draft_publish_unauthorized( From f637726bb7cb6d60d4f9f331f2f2fed2b81167fe Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 18:26:05 +0100 Subject: [PATCH 09/10] Tests for RDM11 are working --- oarepo_requests/{schemas/marshmallow.py => services/schemas.py} | 0 oarepo_requests/{resources => ui}/__init__.py | 0 oarepo_requests/{schemas => ui/resources}/__init__.py | 0 .../components/__init__.py => ui/resources/components.py} | 0 oarepo_requests/{utils => }/utils.py | 2 +- oarepo_requests/utils/__init__.py | 0 tests/test_ui/model.py | 2 +- 7 files changed, 2 insertions(+), 2 deletions(-) rename oarepo_requests/{schemas/marshmallow.py => services/schemas.py} (100%) rename oarepo_requests/{resources => ui}/__init__.py (100%) rename oarepo_requests/{schemas => ui/resources}/__init__.py (100%) rename oarepo_requests/{resources/components/__init__.py => ui/resources/components.py} (100%) rename oarepo_requests/{utils => }/utils.py (93%) delete mode 100644 oarepo_requests/utils/__init__.py diff --git a/oarepo_requests/schemas/marshmallow.py b/oarepo_requests/services/schemas.py similarity index 100% rename from oarepo_requests/schemas/marshmallow.py rename to oarepo_requests/services/schemas.py diff --git a/oarepo_requests/resources/__init__.py b/oarepo_requests/ui/__init__.py similarity index 100% rename from oarepo_requests/resources/__init__.py rename to oarepo_requests/ui/__init__.py diff --git a/oarepo_requests/schemas/__init__.py b/oarepo_requests/ui/resources/__init__.py similarity index 100% rename from oarepo_requests/schemas/__init__.py rename to oarepo_requests/ui/resources/__init__.py diff --git a/oarepo_requests/resources/components/__init__.py b/oarepo_requests/ui/resources/components.py similarity index 100% rename from oarepo_requests/resources/components/__init__.py rename to oarepo_requests/ui/resources/components.py diff --git a/oarepo_requests/utils/utils.py b/oarepo_requests/utils.py similarity index 93% rename from oarepo_requests/utils/utils.py rename to oarepo_requests/utils.py index 537138cc..54705dc9 100644 --- a/oarepo_requests/utils/utils.py +++ b/oarepo_requests/utils.py @@ -1,4 +1,4 @@ -from invenio_requests.proxies import current_request_type_registry +from invenio_requests import current_request_type_registry from invenio_requests.resolvers.registry import ResolverRegistry diff --git a/oarepo_requests/utils/__init__.py b/oarepo_requests/utils/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/test_ui/model.py b/tests/test_ui/model.py index 0e2da275..96f564ad 100644 --- a/tests/test_ui/model.py +++ b/tests/test_ui/model.py @@ -6,7 +6,7 @@ from oarepo_ui.resources.components import PermissionsComponent from thesis.resources.records.ui import ThesisUIJSONSerializer -from oarepo_requests.resources.components import AllowedRequestsComponent +from oarepo_requests.ui.resources.components import AllowedRequestsComponent class ModelUIResourceConfig(RecordsUIResourceConfig): From 4ddfbbb748b73665f0cd710f00823c94e4aefe4c Mon Sep 17 00:00:00 2001 From: Mirek Simek Date: Sun, 17 Dec 2023 18:31:04 +0100 Subject: [PATCH 10/10] version bump --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 20db76d5..9a29f03f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = oarepo-requests -version = 1.0.3 +version = 1.0.4 description = authors = Ronald Krist readme = README.md